00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "asterisk.h"
00035
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 114542 $")
00037
00038 #include <pthread.h>
00039 #include <stdlib.h>
00040 #include <errno.h>
00041 #include <unistd.h>
00042 #include <string.h>
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 #include <sys/time.h>
00046 #include <sys/signal.h>
00047 #include <netinet/in.h>
00048
00049 #include "asterisk/lock.h"
00050 #include "asterisk/file.h"
00051 #include "asterisk/logger.h"
00052 #include "asterisk/channel.h"
00053 #include "asterisk/pbx.h"
00054 #include "asterisk/options.h"
00055 #include "asterisk/causes.h"
00056 #include "asterisk/module.h"
00057 #include "asterisk/translate.h"
00058 #include "asterisk/app.h"
00059 #include "asterisk/say.h"
00060 #include "asterisk/features.h"
00061 #include "asterisk/musiconhold.h"
00062 #include "asterisk/config.h"
00063 #include "asterisk/cli.h"
00064 #include "asterisk/manager.h"
00065 #include "asterisk/utils.h"
00066 #include "asterisk/adsi.h"
00067 #include "asterisk/devicestate.h"
00068 #include "asterisk/monitor.h"
00069 #include "asterisk/indications.h"
00070
00071 #define DEFAULT_PARK_TIME 45000
00072 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
00073 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
00074 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
00075
00076 #define AST_MAX_WATCHERS 256
00077
00078 enum {
00079 AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0),
00080 AST_FEATURE_FLAG_ONPEER = (1 << 1),
00081 AST_FEATURE_FLAG_ONSELF = (1 << 2),
00082 AST_FEATURE_FLAG_BYCALLEE = (1 << 3),
00083 AST_FEATURE_FLAG_BYCALLER = (1 << 4),
00084 AST_FEATURE_FLAG_BYBOTH = (3 << 3),
00085 };
00086
00087 static char *parkedcall = "ParkedCall";
00088 static char *holdedcall = "HoldedCall";
00089
00090 static int parkaddhints = 0;
00091 static int parkingtime = DEFAULT_PARK_TIME;
00092 static char parking_con[AST_MAX_EXTENSION];
00093 static char parking_con_dial[AST_MAX_EXTENSION];
00094 static char parking_ext[AST_MAX_EXTENSION];
00095 static char pickup_ext[AST_MAX_EXTENSION];
00096 static char parkmohclass[MAX_MUSICCLASS];
00097 static int parking_start;
00098 static int parking_stop;
00099
00100 static char courtesytone[256];
00101 static int parkedplay = 0;
00102 static char xfersound[256];
00103 static char xferfailsound[256];
00104
00105 static int parking_offset;
00106 static int parkfindnext;
00107
00108 static int adsipark;
00109
00110 static int transferdigittimeout;
00111 static int featuredigittimeout;
00112
00113 static int atxfernoanswertimeout;
00114
00115 static char *registrar = "res_features";
00116
00117
00118 static char *synopsis = "Answer a parked call";
00119
00120 static char *descrip = "ParkedCall(exten):"
00121 "Used to connect to a parked call. This application is always\n"
00122 "registered internally and does not need to be explicitly added\n"
00123 "into the dialplan, although you should include the 'parkedcalls'\n"
00124 "context.\n";
00125
00126 static char *parkcall = "Park";
00127
00128 static char *synopsis2 = "Park yourself";
00129
00130 static char *descrip2 = "Park():"
00131 "Used to park yourself (typically in combination with a supervised\n"
00132 "transfer to know the parking space). This application is always\n"
00133 "registered internally and does not need to be explicitly added\n"
00134 "into the dialplan, although you should include the 'parkedcalls'\n"
00135 "context (or the context specified in features.conf).\n\n"
00136 "If you set the PARKINGEXTEN variable to an extension in your\n"
00137 "parking context, park() will park the call on that extension, unless\n"
00138 "it already exists. In that case, execution will continue at next\n"
00139 "priority.\n" ;
00140
00141 static char *autoanswerlogin = "AutoanswerLogin";
00142
00143 static char *synopsis3 = "Log in for autoanswer";
00144
00145 static char *descrip3 = "AutoanswerLogin([context]|exten):"
00146 "Used to login to the autoanswer application for an extension.\n";
00147
00148 static char *autoanswer = "Autoanswer";
00149
00150 static char *synopsis4 = "Autoanswer a call";
00151
00152 static char *descrip4 = "Autoanswer([context]|exten):"
00153 "Used to autoanswer a call for an extension.\n";
00154
00155 static struct ast_app *monitor_app = NULL;
00156 static int monitor_ok = 1;
00157
00158 struct parkeduser {
00159 struct ast_channel *chan;
00160 struct timeval start;
00161 int parkingnum;
00162 char parkingexten[AST_MAX_EXTENSION];
00163 char context[AST_MAX_CONTEXT];
00164 char exten[AST_MAX_EXTENSION];
00165 int priority;
00166 int parkingtime;
00167 int notquiteyet;
00168 char peername[1024];
00169 unsigned char moh_trys;
00170 struct parkeduser *next;
00171 };
00172
00173 struct holdeduser {
00174 struct ast_channel *chan;
00175 struct timeval start;
00176 int parkingnum;
00177 int cref;
00178 int tei;
00179
00180 char context[AST_MAX_EXTENSION];
00181 char exten[AST_MAX_EXTENSION];
00182 int priority;
00183 int parkingtime;
00184 char uniqueid[AST_MAX_UNIQUEID];
00185 char uniqueidpeer[AST_MAX_UNIQUEID];
00186 struct holdeduser *next;
00187 };
00188
00189
00190 struct aauser {
00191 struct ast_channel *chan;
00192 struct timeval start;
00193
00194 char exten[AST_MAX_EXTENSION];
00195 char context[AST_MAX_EXTENSION];
00196 int priority;
00197 int notquiteyet;
00198 struct aauser *next;
00199 };
00200
00201
00202 static struct aauser *aalot;
00203 AST_MUTEX_DEFINE_STATIC(autoanswer_lock);
00204 static pthread_t autoanswer_thread;
00205
00206 static struct parkeduser *parkinglot;
00207
00208 static struct holdeduser *holdlist;
00209
00210 AST_MUTEX_DEFINE_STATIC(parking_lock);
00211
00212 AST_MUTEX_DEFINE_STATIC(holding_lock);
00213
00214 static pthread_t parking_thread;
00215
00216 static pthread_t holding_thread;
00217
00218 char *ast_parking_ext(void)
00219 {
00220 return parking_ext;
00221 }
00222
00223 char *ast_pickup_ext(void)
00224 {
00225 return pickup_ext;
00226 }
00227
00228 struct ast_bridge_thread_obj
00229 {
00230 struct ast_bridge_config bconfig;
00231 struct ast_channel *chan;
00232 struct ast_channel *peer;
00233 unsigned int return_to_pbx:1;
00234 };
00235
00236
00237
00238
00239 static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
00240 {
00241 ast_copy_string(chan->context, context, sizeof(chan->context));
00242 ast_copy_string(chan->exten, ext, sizeof(chan->exten));
00243 chan->priority = pri;
00244 }
00245
00246 static void check_goto_on_transfer(struct ast_channel *chan)
00247 {
00248 struct ast_channel *xferchan;
00249 const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
00250 char *x, *goto_on_transfer;
00251 struct ast_frame *f;
00252
00253 if (ast_strlen_zero(val))
00254 return;
00255
00256 goto_on_transfer = ast_strdupa(val);
00257
00258 if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, chan->name)))
00259 return;
00260
00261 for (x = goto_on_transfer; x && *x; x++) {
00262 if (*x == '^')
00263 *x = '|';
00264 }
00265
00266 xferchan->readformat = chan->readformat;
00267 xferchan->writeformat = chan->writeformat;
00268 ast_channel_masquerade(xferchan, chan);
00269 ast_parseable_goto(xferchan, goto_on_transfer);
00270 xferchan->_state = AST_STATE_UP;
00271 ast_clear_flag(xferchan, AST_FLAGS_ALL);
00272 xferchan->_softhangup = 0;
00273 if ((f = ast_read(xferchan))) {
00274 ast_frfree(f);
00275 f = NULL;
00276 ast_pbx_start(xferchan);
00277 } else {
00278 ast_hangup(xferchan);
00279 }
00280 }
00281
00282 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);
00283
00284
00285 static void *ast_bridge_call_thread(void *data)
00286 {
00287 struct ast_bridge_thread_obj *tobj = data;
00288 int res;
00289
00290 tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
00291 tobj->chan->data = tobj->peer->name;
00292 tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
00293 tobj->peer->data = tobj->chan->name;
00294
00295 if (tobj->chan->cdr) {
00296 ast_cdr_reset(tobj->chan->cdr, NULL);
00297 ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
00298 }
00299 if (tobj->peer->cdr) {
00300 ast_cdr_reset(tobj->peer->cdr, NULL);
00301 ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
00302 }
00303
00304 ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
00305
00306 if (tobj->return_to_pbx) {
00307 if (!ast_check_hangup(tobj->peer)) {
00308 ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
00309 res = ast_pbx_start(tobj->peer);
00310 if (res != AST_PBX_SUCCESS)
00311 ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
00312 } else
00313 ast_hangup(tobj->peer);
00314 if (!ast_check_hangup(tobj->chan)) {
00315 ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
00316 res = ast_pbx_start(tobj->chan);
00317 if (res != AST_PBX_SUCCESS)
00318 ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
00319 } else
00320 ast_hangup(tobj->chan);
00321 } else {
00322 ast_hangup(tobj->chan);
00323 ast_hangup(tobj->peer);
00324 }
00325
00326 free(tobj);
00327
00328 return NULL;
00329 }
00330
00331 static void ast_bridge_call_thread_launch(void *data)
00332 {
00333 pthread_t thread;
00334 pthread_attr_t attr;
00335 struct sched_param sched;
00336
00337 pthread_attr_init(&attr);
00338 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00339 ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
00340 pthread_attr_destroy(&attr);
00341 memset(&sched, 0, sizeof(sched));
00342 pthread_setschedparam(thread, SCHED_RR, &sched);
00343 }
00344
00345 static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
00346 {
00347 int res;
00348 int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
00349 char tmp[256];
00350 char *message[5] = {NULL, NULL, NULL, NULL, NULL};
00351
00352 snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
00353 message[0] = tmp;
00354 res = ast_adsi_load_session(chan, NULL, 0, 1);
00355 if (res == -1)
00356 return res;
00357 return ast_adsi_print(chan, message, justify, 1);
00358 }
00359
00360
00361 static void notify_metermaids(char *exten, char *context)
00362 {
00363 if (option_debug > 3)
00364 ast_log(LOG_DEBUG, "Notification of state change to metermaids %s@%s\n", exten, context);
00365
00366
00367 ast_device_state_changed("park:%s@%s", exten, context);
00368 return;
00369 }
00370
00371
00372 static int metermaidstate(const char *data)
00373 {
00374 int res = AST_DEVICE_INVALID;
00375 char *context = ast_strdupa(data);
00376 char *exten;
00377
00378 exten = strsep(&context, "@");
00379 if (!context)
00380 return res;
00381
00382 if (option_debug > 3)
00383 ast_log(LOG_DEBUG, "Checking state of exten %s in context %s\n", exten, context);
00384
00385 res = ast_exists_extension(NULL, context, exten, 1, NULL);
00386
00387 if (!res)
00388 return AST_DEVICE_NOT_INUSE;
00389 else
00390 return AST_DEVICE_INUSE;
00391 }
00392
00393 static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout, char *orig_chan_name)
00394 {
00395 struct parkeduser *pu, *cur;
00396 int i, x = -1, parking_range;
00397 struct ast_context *con;
00398 const char *parkingexten;
00399
00400
00401 if (!(pu = ast_calloc(1, sizeof(*pu))))
00402 return -1;
00403
00404
00405 ast_mutex_lock(&parking_lock);
00406
00407 parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
00408 if (!ast_strlen_zero(parkingexten)) {
00409 if (ast_exists_extension(NULL, parking_con, parkingexten, 1, NULL)) {
00410 ast_mutex_unlock(&parking_lock);
00411 free(pu);
00412 ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
00413 return 1;
00414 }
00415 ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten));
00416 x = atoi(parkingexten);
00417 } else {
00418
00419 parking_range = parking_stop - parking_start+1;
00420 for (i = 0; i < parking_range; i++) {
00421 x = (i + parking_offset) % parking_range + parking_start;
00422 cur = parkinglot;
00423 while(cur) {
00424 if (cur->parkingnum == x)
00425 break;
00426 cur = cur->next;
00427 }
00428 if (!cur)
00429 break;
00430 }
00431
00432 if (!(i < parking_range)) {
00433 ast_log(LOG_WARNING, "No more parking spaces\n");
00434 free(pu);
00435 ast_mutex_unlock(&parking_lock);
00436 return -1;
00437 }
00438
00439 if (parkfindnext)
00440 parking_offset = x - parking_start + 1;
00441 }
00442
00443 chan->appl = "Parked Call";
00444 chan->data = NULL;
00445
00446 pu->chan = chan;
00447
00448
00449 if (chan != peer) {
00450 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
00451 S_OR(parkmohclass, NULL),
00452 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
00453 }
00454
00455 pu->start = ast_tvnow();
00456 pu->parkingnum = x;
00457 pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
00458 if (extout)
00459 *extout = x;
00460
00461 if (peer)
00462 ast_copy_string(pu->peername, peer->name, sizeof(pu->peername));
00463
00464
00465
00466 ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
00467 ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
00468 pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
00469 pu->next = parkinglot;
00470 parkinglot = pu;
00471
00472
00473 if (peer == chan)
00474 pu->notquiteyet = 1;
00475 ast_mutex_unlock(&parking_lock);
00476
00477 pthread_kill(parking_thread, SIGURG);
00478 if (option_verbose > 1)
00479 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));
00480
00481 if (pu->parkingnum != -1)
00482 snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
00483 manager_event(EVENT_FLAG_CALL, "ParkedCall",
00484 "Exten: %s\r\n"
00485 "Channel: %s\r\n"
00486 "From: %s\r\n"
00487 "Timeout: %ld\r\n"
00488 "CallerID: %s\r\n"
00489 "CallerIDName: %s\r\n"
00490 "Uniqueid: %s\r\n",
00491 pu->parkingexten, pu->chan->name, peer ? peer->name : "",
00492 (long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
00493 S_OR(pu->chan->cid.cid_num, "<unknown>"),
00494 S_OR(pu->chan->cid.cid_name, "<unknown>"),
00495 pu->chan->uniqueid
00496 );
00497
00498 if (peer && adsipark && ast_adsi_available(peer)) {
00499 adsi_announce_park(peer, pu->parkingexten);
00500 ast_adsi_unload_session(peer);
00501 }
00502
00503 con = ast_context_find(parking_con);
00504 if (!con)
00505 con = ast_context_create(NULL, parking_con, registrar);
00506 if (!con)
00507 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
00508
00509 if (peer && ((pu->parkingnum != -1 && ast_strlen_zero(orig_chan_name)) || !strcasecmp(peer->name, orig_chan_name))) {
00510
00511 ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
00512 ast_say_digits(peer, pu->parkingnum, "", peer->language);
00513 ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
00514 }
00515 if (con) {
00516 if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, strdup(pu->parkingexten), ast_free, registrar))
00517 notify_metermaids(pu->parkingexten, parking_con);
00518 }
00519 if (pu->notquiteyet) {
00520
00521 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
00522 S_OR(parkmohclass, NULL),
00523 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
00524 pu->notquiteyet = 0;
00525 pthread_kill(parking_thread, SIGURG);
00526 }
00527 return 0;
00528 }
00529
00530
00531
00532
00533 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
00534 {
00535 return park_call_full(chan, peer, timeout, extout, NULL);
00536 }
00537
00538 int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
00539 {
00540 struct ast_channel *chan;
00541 struct ast_frame *f;
00542 char *orig_chan_name = NULL;
00543
00544
00545 if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
00546 ast_log(LOG_WARNING, "Unable to create parked channel\n");
00547 return -1;
00548 }
00549
00550
00551 chan->readformat = rchan->readformat;
00552 chan->writeformat = rchan->writeformat;
00553 ast_channel_masquerade(chan, rchan);
00554
00555
00556 set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
00557
00558
00559 f = ast_read(chan);
00560 if (f)
00561 ast_frfree(f);
00562
00563 orig_chan_name = ast_strdupa(chan->name);
00564
00565 park_call_full(chan, peer, timeout, extout, orig_chan_name);
00566
00567 return 0;
00568 }
00569
00570
00571 #define FEATURE_RETURN_HANGUP -1
00572 #define FEATURE_RETURN_SUCCESSBREAK 0
00573 #define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE
00574 #define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER
00575 #define FEATURE_RETURN_PASSDIGITS 21
00576 #define FEATURE_RETURN_STOREDIGITS 22
00577 #define FEATURE_RETURN_SUCCESS 23
00578 #define FEATURE_RETURN_KEEPTRYING 24
00579
00580 #define FEATURE_SENSE_CHAN (1 << 0)
00581 #define FEATURE_SENSE_PEER (1 << 1)
00582
00583
00584
00585
00586 static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
00587 struct ast_channel *peer, struct ast_channel *chan, int sense)
00588 {
00589 if (sense == FEATURE_SENSE_PEER) {
00590 *caller = peer;
00591 *callee = chan;
00592 } else {
00593 *callee = peer;
00594 *caller = chan;
00595 }
00596 }
00597
00598
00599 static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
00600 {
00601 struct ast_channel *parker;
00602 struct ast_channel *parkee;
00603 int res = 0;
00604 struct ast_module_user *u;
00605
00606 u = ast_module_user_add(chan);
00607
00608 set_peers(&parker, &parkee, peer, chan, sense);
00609
00610
00611 strcpy(chan->exten, "s");
00612 chan->priority = 1;
00613 if (chan->_state != AST_STATE_UP)
00614 res = ast_answer(chan);
00615 if (!res)
00616 res = ast_safe_sleep(chan, 1000);
00617 if (!res)
00618 res = ast_park_call(parkee, parker, 0, NULL);
00619
00620 ast_module_user_remove(u);
00621
00622 if (!res) {
00623 if (sense == FEATURE_SENSE_CHAN)
00624 res = AST_PBX_NO_HANGUP_PEER;
00625 else
00626 res = AST_PBX_KEEPALIVE;
00627 }
00628 return res;
00629
00630 }
00631
00632 static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
00633 {
00634 char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
00635 int x = 0;
00636 size_t len;
00637 struct ast_channel *caller_chan, *callee_chan;
00638
00639 if (!monitor_ok) {
00640 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
00641 return -1;
00642 }
00643
00644 if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
00645 monitor_ok = 0;
00646 ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
00647 return -1;
00648 }
00649
00650 set_peers(&caller_chan, &callee_chan, peer, chan, sense);
00651
00652 if (!ast_strlen_zero(courtesytone)) {
00653 if (ast_autoservice_start(callee_chan))
00654 return -1;
00655 if (ast_stream_and_wait(caller_chan, courtesytone, caller_chan->language, "")) {
00656 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
00657 ast_autoservice_stop(callee_chan);
00658 return -1;
00659 }
00660 if (ast_autoservice_stop(callee_chan))
00661 return -1;
00662 }
00663
00664 if (callee_chan->monitor) {
00665 if (option_verbose > 3)
00666 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to stop recording call.\n", code);
00667 ast_monitor_stop(callee_chan, 1);
00668 return FEATURE_RETURN_SUCCESS;
00669 }
00670
00671 if (caller_chan && callee_chan) {
00672 const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
00673 const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
00674
00675 if (!touch_format)
00676 touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
00677
00678 if (!touch_monitor)
00679 touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
00680
00681 if (touch_monitor) {
00682 len = strlen(touch_monitor) + 50;
00683 args = alloca(len);
00684 touch_filename = alloca(len);
00685 snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
00686 snprintf(args, len, "%s|%s|m", (touch_format) ? touch_format : "wav", touch_filename);
00687 } else {
00688 caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
00689 callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
00690 len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
00691 args = alloca(len);
00692 touch_filename = alloca(len);
00693 snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
00694 snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename);
00695 }
00696
00697 for( x = 0; x < strlen(args); x++) {
00698 if (args[x] == '/')
00699 args[x] = '-';
00700 }
00701
00702 if (option_verbose > 3)
00703 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to record call. filename: %s\n", code, args);
00704
00705 pbx_exec(callee_chan, monitor_app, args);
00706 pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
00707 pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
00708
00709 return FEATURE_RETURN_SUCCESS;
00710 }
00711
00712 ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
00713 return -1;
00714 }
00715
00716 static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
00717 {
00718 if (option_verbose > 3)
00719 ast_verbose(VERBOSE_PREFIX_3 "User hit '%s' to disconnect call.\n", code);
00720 return FEATURE_RETURN_HANGUP;
00721 }
00722
00723 static int finishup(struct ast_channel *chan)
00724 {
00725 ast_indicate(chan, AST_CONTROL_UNHOLD);
00726
00727 return ast_autoservice_stop(chan);
00728 }
00729
00730
00731 static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
00732 {
00733 const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
00734 if (ast_strlen_zero(s))
00735 s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
00736 if (ast_strlen_zero(s))
00737 s = transferer->macrocontext;
00738 if (ast_strlen_zero(s))
00739 s = transferer->context;
00740 return s;
00741 }
00742
00743 static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
00744 {
00745 struct ast_channel *transferer;
00746 struct ast_channel *transferee;
00747 const char *transferer_real_context;
00748 char xferto[256];
00749 int res;
00750
00751 set_peers(&transferer, &transferee, peer, chan, sense);
00752 transferer_real_context = real_ctx(transferer, transferee);
00753
00754 ast_autoservice_start(transferee);
00755 ast_indicate(transferee, AST_CONTROL_HOLD);
00756
00757 memset(xferto, 0, sizeof(xferto));
00758
00759
00760 res = ast_stream_and_wait(transferer, "pbx-transfer", transferer->language, AST_DIGIT_ANY);
00761 if (res < 0) {
00762 finishup(transferee);
00763 return -1;
00764 }
00765 if (res > 0)
00766 xferto[0] = (char) res;
00767
00768 ast_stopstream(transferer);
00769 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
00770 if (res < 0) {
00771 finishup(transferee);
00772 return res;
00773 }
00774 if (!strcmp(xferto, ast_parking_ext())) {
00775 res = finishup(transferee);
00776 if (res)
00777 res = -1;
00778 else if (!ast_park_call(transferee, transferer, 0, NULL)) {
00779
00780
00781
00782
00783 return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
00784 } else {
00785 ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
00786 }
00787
00788 } else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
00789 pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", transferee->name);
00790 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
00791 res=finishup(transferee);
00792 if (!transferer->cdr) {
00793 transferer->cdr=ast_cdr_alloc();
00794 if (transferer) {
00795 ast_cdr_init(transferer->cdr, transferer);
00796 ast_cdr_start(transferer->cdr);
00797 }
00798 }
00799 if (transferer->cdr) {
00800 ast_cdr_setdestchan(transferer->cdr, transferee->name);
00801 ast_cdr_setapp(transferer->cdr, "BLINDTRANSFER","");
00802 }
00803 if (!transferee->pbx) {
00804
00805 if (option_verbose > 2)
00806 ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
00807 ,transferee->name, xferto, transferer_real_context);
00808 if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
00809 ast_log(LOG_WARNING, "Async goto failed :-(\n");
00810 res = -1;
00811 } else {
00812
00813 set_c_e_p(transferee, transferer_real_context, xferto, 0);
00814 }
00815 check_goto_on_transfer(transferer);
00816 return res;
00817 } else {
00818 if (option_verbose > 2)
00819 ast_verbose(VERBOSE_PREFIX_3 "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
00820 }
00821 if (ast_stream_and_wait(transferer, xferfailsound, transferer->language, AST_DIGIT_ANY) < 0 ) {
00822 finishup(transferee);
00823 return -1;
00824 }
00825 ast_stopstream(transferer);
00826 res = finishup(transferee);
00827 if (res) {
00828 if (option_verbose > 1)
00829 ast_verbose(VERBOSE_PREFIX_2 "Hungup during autoservice stop on '%s'\n", transferee->name);
00830 return res;
00831 }
00832 return FEATURE_RETURN_SUCCESS;
00833 }
00834
00835 static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
00836 {
00837 if (ast_channel_make_compatible(c, newchan) < 0) {
00838 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
00839 c->name, newchan->name);
00840 ast_hangup(newchan);
00841 return -1;
00842 }
00843 return 0;
00844 }
00845
00846 static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
00847 {
00848 struct ast_channel *transferer;
00849 struct ast_channel *transferee;
00850 const char *transferer_real_context;
00851 char xferto[256] = "";
00852 int res;
00853 int outstate=0;
00854 struct ast_channel *newchan;
00855 struct ast_channel *xferchan;
00856 struct ast_bridge_thread_obj *tobj;
00857 struct ast_bridge_config bconfig;
00858 struct ast_frame *f;
00859 int l;
00860
00861 if (option_debug)
00862 ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
00863 set_peers(&transferer, &transferee, peer, chan, sense);
00864 transferer_real_context = real_ctx(transferer, transferee);
00865
00866 ast_autoservice_start(transferee);
00867 ast_indicate(transferee, AST_CONTROL_HOLD);
00868
00869
00870 res = ast_stream_and_wait(transferer, "pbx-transfer", transferer->language, AST_DIGIT_ANY);
00871 if (res < 0) {
00872 finishup(transferee);
00873 return res;
00874 }
00875 if (res > 0)
00876 xferto[0] = (char) res;
00877
00878
00879 res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
00880 if (res < 0) {
00881 finishup(transferee);
00882 return res;
00883 }
00884 if (res == 0) {
00885 ast_log(LOG_WARNING, "Did not read data.\n");
00886 finishup(transferee);
00887 if (ast_stream_and_wait(transferer, "beeperr", transferer->language, ""))
00888 return -1;
00889 return FEATURE_RETURN_SUCCESS;
00890 }
00891
00892
00893 if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
00894 ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
00895 finishup(transferee);
00896 if (ast_stream_and_wait(transferer, "beeperr", transferer->language, ""))
00897 return -1;
00898 return FEATURE_RETURN_SUCCESS;
00899 }
00900
00901 l = strlen(xferto);
00902 snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);
00903 newchan = ast_feature_request_and_dial(transferer, "Local", ast_best_codec(transferer->nativeformats),
00904 xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, transferer->language);
00905 ast_indicate(transferer, -1);
00906 if (!newchan) {
00907 finishup(transferee);
00908
00909 if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
00910 ast_stream_and_wait(transferer, xferfailsound, transferer->language, ""))
00911 return -1;
00912 return FEATURE_RETURN_SUCCESS;
00913 }
00914
00915 if (check_compat(transferer, newchan)) {
00916
00917 finishup(transferee);
00918 return -1;
00919 }
00920 memset(&bconfig,0,sizeof(struct ast_bridge_config));
00921 ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
00922 ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
00923 res = ast_bridge_call(transferer, newchan, &bconfig);
00924 if (newchan->_softhangup || !transferer->_softhangup) {
00925 ast_hangup(newchan);
00926 if (ast_stream_and_wait(transferer, xfersound, transferer->language, ""))
00927 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
00928 finishup(transferee);
00929 transferer->_softhangup = 0;
00930 return FEATURE_RETURN_SUCCESS;
00931 }
00932
00933 if (check_compat(transferee, newchan)) {
00934 finishup(transferee);
00935 return -1;
00936 }
00937
00938 ast_indicate(transferee, AST_CONTROL_UNHOLD);
00939
00940 if ((ast_autoservice_stop(transferee) < 0)
00941 || (ast_waitfordigit(transferee, 100) < 0)
00942 || (ast_waitfordigit(newchan, 100) < 0)
00943 || ast_check_hangup(transferee)
00944 || ast_check_hangup(newchan)) {
00945 ast_hangup(newchan);
00946 return -1;
00947 }
00948
00949 xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
00950 if (!xferchan) {
00951 ast_hangup(newchan);
00952 return -1;
00953 }
00954
00955 xferchan->visible_indication = transferer->visible_indication;
00956 xferchan->readformat = transferee->readformat;
00957 xferchan->writeformat = transferee->writeformat;
00958 ast_channel_masquerade(xferchan, transferee);
00959 ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
00960 xferchan->_state = AST_STATE_UP;
00961 ast_clear_flag(xferchan, AST_FLAGS_ALL);
00962 xferchan->_softhangup = 0;
00963
00964 if ((f = ast_read(xferchan)))
00965 ast_frfree(f);
00966
00967 newchan->_state = AST_STATE_UP;
00968 ast_clear_flag(newchan, AST_FLAGS_ALL);
00969 newchan->_softhangup = 0;
00970
00971 tobj = ast_calloc(1, sizeof(struct ast_bridge_thread_obj));
00972 if (!tobj) {
00973 ast_hangup(xferchan);
00974 ast_hangup(newchan);
00975 return -1;
00976 }
00977 tobj->chan = newchan;
00978 tobj->peer = xferchan;
00979 tobj->bconfig = *config;
00980
00981 if (ast_stream_and_wait(newchan, xfersound, newchan->language, ""))
00982 ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
00983 ast_bridge_call_thread_launch(tobj);
00984 return -1;
00985 }
00986
00987
00988
00989 #define FEATURES_COUNT (sizeof(builtin_features) / sizeof(builtin_features[0]))
00990
00991 AST_RWLOCK_DEFINE_STATIC(features_lock);
00992
00993 static struct ast_call_feature builtin_features[] =
00994 {
00995 { AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
00996 { AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
00997 { AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
00998 { AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
00999 { AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
01000 };
01001
01002
01003 static AST_LIST_HEAD_STATIC(feature_list,ast_call_feature);
01004
01005
01006 void ast_register_feature(struct ast_call_feature *feature)
01007 {
01008 if (!feature) {
01009 ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
01010 return;
01011 }
01012
01013 AST_LIST_LOCK(&feature_list);
01014 AST_LIST_INSERT_HEAD(&feature_list,feature,feature_entry);
01015 AST_LIST_UNLOCK(&feature_list);
01016
01017 if (option_verbose >= 2)
01018 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname);
01019 }
01020
01021
01022 void ast_unregister_feature(struct ast_call_feature *feature)
01023 {
01024 if (!feature)
01025 return;
01026
01027 AST_LIST_LOCK(&feature_list);
01028 AST_LIST_REMOVE(&feature_list,feature,feature_entry);
01029 AST_LIST_UNLOCK(&feature_list);
01030 free(feature);
01031 }
01032
01033
01034 static void ast_unregister_features(void)
01035 {
01036 struct ast_call_feature *feature;
01037
01038 AST_LIST_LOCK(&feature_list);
01039 while ((feature = AST_LIST_REMOVE_HEAD(&feature_list,feature_entry)))
01040 free(feature);
01041 AST_LIST_UNLOCK(&feature_list);
01042 }
01043
01044
01045 static struct ast_call_feature *find_dynamic_feature(const char *name)
01046 {
01047 struct ast_call_feature *tmp;
01048
01049 AST_LIST_TRAVERSE(&feature_list, tmp, feature_entry) {
01050 if (!strcasecmp(tmp->sname, name))
01051 break;
01052 }
01053
01054 return tmp;
01055 }
01056
01057
01058 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
01059 {
01060 struct ast_app *app;
01061 struct ast_call_feature *feature = data;
01062 struct ast_channel *work, *idle;
01063 int res;
01064
01065 if (!feature) {
01066 ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
01067 return -1;
01068 }
01069
01070 if (sense == FEATURE_SENSE_CHAN) {
01071 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
01072 return FEATURE_RETURN_KEEPTRYING;
01073 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
01074 work = chan;
01075 idle = peer;
01076 } else {
01077 work = peer;
01078 idle = chan;
01079 }
01080 } else {
01081 if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
01082 return FEATURE_RETURN_KEEPTRYING;
01083 if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
01084 work = peer;
01085 idle = chan;
01086 } else {
01087 work = chan;
01088 idle = peer;
01089 }
01090 }
01091
01092 if (!(app = pbx_findapp(feature->app))) {
01093 ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
01094 return -2;
01095 }
01096
01097 ast_autoservice_start(idle);
01098
01099 if (!ast_strlen_zero(feature->moh_class))
01100 ast_moh_start(idle, feature->moh_class, NULL);
01101
01102 res = pbx_exec(work, app, feature->app_args);
01103
01104 if (!ast_strlen_zero(feature->moh_class))
01105 ast_moh_stop(idle);
01106
01107 ast_autoservice_stop(idle);
01108
01109 if (res == AST_PBX_KEEPALIVE)
01110 return FEATURE_RETURN_PBX_KEEPALIVE;
01111 else if (res == AST_PBX_NO_HANGUP_PEER)
01112 return FEATURE_RETURN_NO_HANGUP_PEER;
01113 else if (res)
01114 return FEATURE_RETURN_SUCCESSBREAK;
01115
01116 return FEATURE_RETURN_SUCCESS;
01117 }
01118
01119 static void unmap_features(void)
01120 {
01121 int x;
01122
01123 ast_rwlock_wrlock(&features_lock);
01124 for (x = 0; x < FEATURES_COUNT; x++)
01125 strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
01126 ast_rwlock_unlock(&features_lock);
01127 }
01128
01129 static int remap_feature(const char *name, const char *value)
01130 {
01131 int x, res = -1;
01132
01133 ast_rwlock_wrlock(&features_lock);
01134 for (x = 0; x < FEATURES_COUNT; x++) {
01135 if (strcasecmp(builtin_features[x].sname, name))
01136 continue;
01137
01138 ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
01139 res = 0;
01140 break;
01141 }
01142 ast_rwlock_unlock(&features_lock);
01143
01144 return res;
01145 }
01146
01147 static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
01148 {
01149 int x;
01150 struct ast_flags features;
01151 int res = FEATURE_RETURN_PASSDIGITS;
01152 struct ast_call_feature *feature;
01153 const char *dynamic_features;
01154 char *tmp, *tok;
01155
01156 if (sense == FEATURE_SENSE_CHAN) {
01157 ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
01158 dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
01159 } else {
01160 ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
01161 dynamic_features = pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES");
01162 }
01163 if (option_debug > 2)
01164 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);
01165
01166 ast_rwlock_rdlock(&features_lock);
01167 for (x = 0; x < FEATURES_COUNT; x++) {
01168 if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
01169 !ast_strlen_zero(builtin_features[x].exten)) {
01170
01171 if (!strcmp(builtin_features[x].exten, code)) {
01172 res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
01173 break;
01174 } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
01175 if (res == FEATURE_RETURN_PASSDIGITS)
01176 res = FEATURE_RETURN_STOREDIGITS;
01177 }
01178 }
01179 }
01180 ast_rwlock_unlock(&features_lock);
01181
01182 if (ast_strlen_zero(dynamic_features))
01183 return res;
01184
01185 tmp = ast_strdupa(dynamic_features);
01186
01187 while ((tok = strsep(&tmp, "#"))) {
01188 AST_LIST_LOCK(&feature_list);
01189 if (!(feature = find_dynamic_feature(tok))) {
01190 AST_LIST_UNLOCK(&feature_list);
01191 continue;
01192 }
01193
01194
01195 if (!strcmp(feature->exten, code)) {
01196 if (option_verbose > 2)
01197 ast_verbose(VERBOSE_PREFIX_3 " Feature Found: %s exten: %s\n",feature->sname, tok);
01198 res = feature->operation(chan, peer, config, code, sense, feature);
01199 if (res != FEATURE_RETURN_KEEPTRYING) {
01200 AST_LIST_UNLOCK(&feature_list);
01201 break;
01202 }
01203 res = FEATURE_RETURN_PASSDIGITS;
01204 } else if (!strncmp(feature->exten, code, strlen(code)))
01205 res = FEATURE_RETURN_STOREDIGITS;
01206
01207 AST_LIST_UNLOCK(&feature_list);
01208 }
01209
01210 return res;
01211 }
01212
01213 static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
01214 {
01215 int x;
01216
01217 ast_clear_flag(config, AST_FLAGS_ALL);
01218
01219 ast_rwlock_rdlock(&features_lock);
01220 for (x = 0; x < FEATURES_COUNT; x++) {
01221 if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
01222 continue;
01223
01224 if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
01225 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
01226
01227 if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
01228 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
01229 }
01230 ast_rwlock_unlock(&features_lock);
01231
01232 if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
01233 const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
01234
01235 if (dynamic_features) {
01236 char *tmp = ast_strdupa(dynamic_features);
01237 char *tok;
01238 struct ast_call_feature *feature;
01239
01240
01241 while ((tok = strsep(&tmp, "#"))) {
01242 AST_LIST_LOCK(&feature_list);
01243 if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
01244 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
01245 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
01246 if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
01247 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
01248 }
01249 AST_LIST_UNLOCK(&feature_list);
01250 }
01251 }
01252 }
01253 }
01254
01255
01256 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)
01257 {
01258 int state = 0;
01259 int cause = 0;
01260 int to;
01261 struct ast_channel *chan;
01262 struct ast_channel *monitor_chans[2];
01263 struct ast_channel *active_channel;
01264 int res = 0, ready = 0;
01265
01266 if ((chan = ast_request(type, format, data, &cause))) {
01267 ast_set_callerid(chan, cid_num, cid_name, cid_num);
01268 ast_string_field_set(chan, language, language);
01269 ast_channel_inherit_variables(caller, chan);
01270 pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
01271 if (!chan->cdr) {
01272 chan->cdr=ast_cdr_alloc();
01273 if (chan->cdr) {
01274 ast_cdr_init(chan->cdr, chan);
01275 ast_cdr_start(chan->cdr);
01276 }
01277 }
01278
01279 if (!ast_call(chan, data, timeout)) {
01280 struct timeval started;
01281 int x, len = 0;
01282 char *disconnect_code = NULL, *dialed_code = NULL;
01283
01284 ast_indicate(caller, AST_CONTROL_RINGING);
01285
01286 ast_rwlock_rdlock(&features_lock);
01287 for (x = 0; x < FEATURES_COUNT; x++) {
01288 if (strcasecmp(builtin_features[x].sname, "disconnect"))
01289 continue;
01290
01291 disconnect_code = builtin_features[x].exten;
01292 len = strlen(disconnect_code) + 1;
01293 dialed_code = alloca(len);
01294 memset(dialed_code, 0, len);
01295 break;
01296 }
01297 ast_rwlock_unlock(&features_lock);
01298 x = 0;
01299 started = ast_tvnow();
01300 to = timeout;
01301 while (!ast_check_hangup(caller) && timeout && (chan->_state != AST_STATE_UP)) {
01302 struct ast_frame *f = NULL;
01303
01304 monitor_chans[0] = caller;
01305 monitor_chans[1] = chan;
01306 active_channel = ast_waitfor_n(monitor_chans, 2, &to);
01307
01308
01309 if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
01310 state = AST_CONTROL_UNHOLD;
01311 ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
01312 break;
01313 }
01314
01315 if (!active_channel)
01316 continue;
01317
01318 if (chan && (chan == active_channel)){
01319 f = ast_read(chan);
01320 if (f == NULL) {
01321 state = AST_CONTROL_HANGUP;
01322 res = 0;
01323 break;
01324 }
01325
01326 if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
01327 if (f->subclass == AST_CONTROL_RINGING) {
01328 state = f->subclass;
01329 if (option_verbose > 2)
01330 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", chan->name);
01331 ast_indicate(caller, AST_CONTROL_RINGING);
01332 } else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
01333 state = f->subclass;
01334 if (option_verbose > 2)
01335 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", chan->name);
01336 ast_indicate(caller, AST_CONTROL_BUSY);
01337 ast_frfree(f);
01338 f = NULL;
01339 break;
01340 } else if (f->subclass == AST_CONTROL_ANSWER) {
01341
01342 state = f->subclass;
01343 ast_frfree(f);
01344 f = NULL;
01345 ready=1;
01346 break;
01347 } else if (f->subclass != -1) {
01348 ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
01349 }
01350
01351 }
01352
01353 } else if (caller && (active_channel == caller)) {
01354 f = ast_read(caller);
01355 if (f == NULL) {
01356 if (caller->_softhangup && !chan->_softhangup) {
01357
01358 ready = 1;
01359 break;
01360 }
01361 state = AST_CONTROL_HANGUP;
01362 res = 0;
01363 break;
01364 }
01365
01366 if (f->frametype == AST_FRAME_DTMF) {
01367 dialed_code[x++] = f->subclass;
01368 dialed_code[x] = '\0';
01369 if (strlen(dialed_code) == len) {
01370 x = 0;
01371 } else if (x && strncmp(dialed_code, disconnect_code, x)) {
01372 x = 0;
01373 dialed_code[x] = '\0';
01374 }
01375 if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
01376
01377 state = AST_CONTROL_UNHOLD;
01378 ast_frfree(f);
01379 f = NULL;
01380 break;
01381 }
01382 }
01383 }
01384 if (f)
01385 ast_frfree(f);
01386 }
01387 } else
01388 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
01389 } else {
01390 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01391 switch(cause) {
01392 case AST_CAUSE_BUSY:
01393 state = AST_CONTROL_BUSY;
01394 break;
01395 case AST_CAUSE_CONGESTION:
01396 state = AST_CONTROL_CONGESTION;
01397 break;
01398 }
01399 }
01400
01401 ast_indicate(caller, -1);
01402 if (chan && ready) {
01403 if (chan->_state == AST_STATE_UP)
01404 state = AST_CONTROL_ANSWER;
01405 res = 0;
01406 } else if(chan) {
01407 res = -1;
01408 ast_hangup(chan);
01409 chan = NULL;
01410 } else {
01411 res = -1;
01412 }
01413
01414 if (outstate)
01415 *outstate = state;
01416
01417 if (chan && res <= 0) {
01418 if (chan->cdr || (chan->cdr = ast_cdr_alloc())) {
01419 char tmp[256];
01420 ast_cdr_init(chan->cdr, chan);
01421 snprintf(tmp, 256, "%s/%s", type, (char *)data);
01422 ast_cdr_setapp(chan->cdr,"Dial",tmp);
01423 ast_cdr_update(chan);
01424 ast_cdr_start(chan->cdr);
01425 ast_cdr_end(chan->cdr);
01426
01427 if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
01428 ast_cdr_failed(chan->cdr);
01429 } else {
01430 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01431 }
01432 }
01433
01434 return chan;
01435 }
01436
01437 int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
01438 {
01439
01440
01441 struct ast_frame *f;
01442 struct ast_channel *who;
01443 char chan_featurecode[FEATURE_MAX_LEN + 1]="";
01444 char peer_featurecode[FEATURE_MAX_LEN + 1]="";
01445 int res;
01446 int diff;
01447 int hasfeatures=0;
01448 int hadfeatures=0;
01449 struct ast_option_header *aoh;
01450 struct ast_bridge_config backup_config;
01451 struct ast_cdr *bridge_cdr;
01452
01453 memset(&backup_config, 0, sizeof(backup_config));
01454
01455 config->start_time = ast_tvnow();
01456
01457 if (chan && peer) {
01458 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
01459 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
01460 } else if (chan)
01461 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
01462
01463 if (monitor_ok) {
01464 const char *monitor_exec;
01465 struct ast_channel *src = NULL;
01466 if (!monitor_app) {
01467 if (!(monitor_app = pbx_findapp("Monitor")))
01468 monitor_ok=0;
01469 }
01470 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
01471 src = chan;
01472 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
01473 src = peer;
01474 if (monitor_app && src) {
01475 char *tmp = ast_strdupa(monitor_exec);
01476 pbx_exec(src, monitor_app, tmp);
01477 }
01478 }
01479
01480 set_config_flags(chan, peer, config);
01481 config->firstpass = 1;
01482
01483
01484 if (ast_answer(chan))
01485 return -1;
01486 peer->appl = "Bridged Call";
01487 peer->data = chan->name;
01488
01489
01490 if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
01491 char tmp[256];
01492 if (!ast_strlen_zero(chan->cdr->userfield)) {
01493 snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
01494 ast_cdr_appenduserfield(chan, tmp);
01495 } else
01496 ast_cdr_setuserfield(chan, peer->cdr->userfield);
01497
01498 free(peer->cdr);
01499 peer->cdr = NULL;
01500 }
01501
01502 for (;;) {
01503 struct ast_channel *other;
01504
01505 res = ast_channel_bridge(chan, peer, config, &f, &who);
01506
01507 if (config->feature_timer) {
01508
01509 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
01510 config->feature_timer -= diff;
01511 if (hasfeatures) {
01512
01513
01514
01515 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
01516 if (option_debug)
01517 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n");
01518 config->feature_timer = 0;
01519 who = chan;
01520 if (f)
01521 ast_frfree(f);
01522 f = NULL;
01523 res = 0;
01524 } else if (config->feature_timer <= 0) {
01525
01526
01527 if (option_debug)
01528 ast_log(LOG_DEBUG, "Timed out for feature!\n");
01529 if (!ast_strlen_zero(peer_featurecode)) {
01530 ast_dtmf_stream(chan, peer, peer_featurecode, 0);
01531 memset(peer_featurecode, 0, sizeof(peer_featurecode));
01532 }
01533 if (!ast_strlen_zero(chan_featurecode)) {
01534 ast_dtmf_stream(peer, chan, chan_featurecode, 0);
01535 memset(chan_featurecode, 0, sizeof(chan_featurecode));
01536 }
01537 if (f)
01538 ast_frfree(f);
01539 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
01540 if (!hasfeatures) {
01541
01542 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
01543 memset(&backup_config, 0, sizeof(backup_config));
01544 }
01545 hadfeatures = hasfeatures;
01546
01547 continue;
01548 } else if (!f) {
01549
01550
01551
01552 continue;
01553 }
01554 } else {
01555 if (config->feature_timer <=0) {
01556
01557 config->feature_timer = 0;
01558 who = chan;
01559 if (f)
01560 ast_frfree(f);
01561 f = NULL;
01562 res = 0;
01563 }
01564 }
01565 }
01566 if (res < 0) {
01567 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
01568 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
01569 return -1;
01570 }
01571
01572 if (!f || (f->frametype == AST_FRAME_CONTROL &&
01573 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
01574 f->subclass == AST_CONTROL_CONGESTION ) ) ) {
01575 res = -1;
01576 break;
01577 }
01578
01579 other = (who == chan) ? peer : chan;
01580 if (f->frametype == AST_FRAME_CONTROL) {
01581 switch (f->subclass) {
01582 case AST_CONTROL_RINGING:
01583 case AST_CONTROL_FLASH:
01584 case -1:
01585 ast_indicate(other, f->subclass);
01586 break;
01587 case AST_CONTROL_HOLD:
01588 case AST_CONTROL_UNHOLD:
01589 ast_indicate_data(other, f->subclass, f->data, f->datalen);
01590 break;
01591 case AST_CONTROL_OPTION:
01592 aoh = f->data;
01593
01594 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
01595 ast_channel_setoption(other, ntohs(aoh->option), aoh->data,
01596 f->datalen - sizeof(struct ast_option_header), 0);
01597 }
01598 break;
01599 }
01600 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
01601
01602 } else if (f->frametype == AST_FRAME_DTMF) {
01603 char *featurecode;
01604 int sense;
01605
01606 hadfeatures = hasfeatures;
01607
01608 if (who == chan) {
01609 sense = FEATURE_SENSE_CHAN;
01610 featurecode = chan_featurecode;
01611 } else {
01612 sense = FEATURE_SENSE_PEER;
01613 featurecode = peer_featurecode;
01614 }
01615
01616
01617
01618
01619 featurecode[strlen(featurecode)] = f->subclass;
01620
01621 ast_frfree(f);
01622 f = NULL;
01623 config->feature_timer = backup_config.feature_timer;
01624 res = ast_feature_interpret(chan, peer, config, featurecode, sense);
01625 switch(res) {
01626 case FEATURE_RETURN_PASSDIGITS:
01627 ast_dtmf_stream(other, who, featurecode, 0);
01628
01629 case FEATURE_RETURN_SUCCESS:
01630 memset(featurecode, 0, sizeof(chan_featurecode));
01631 break;
01632 }
01633 if (res >= FEATURE_RETURN_PASSDIGITS) {
01634 res = 0;
01635 } else
01636 break;
01637 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
01638 if (hadfeatures && !hasfeatures) {
01639
01640 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
01641 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
01642 } else if (hasfeatures) {
01643 if (!hadfeatures) {
01644
01645 memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
01646
01647 config->play_warning = 0;
01648 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
01649 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
01650 config->warning_freq = 0;
01651 config->warning_sound = NULL;
01652 config->end_sound = NULL;
01653 config->start_sound = NULL;
01654 config->firstpass = 0;
01655 }
01656 config->start_time = ast_tvnow();
01657 config->feature_timer = featuredigittimeout;
01658 if (option_debug)
01659 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
01660 }
01661 }
01662 if (f)
01663 ast_frfree(f);
01664
01665 }
01666
01667
01668 bridge_cdr = ast_cdr_alloc();
01669 if (bridge_cdr) {
01670 if (chan->cdr && peer->cdr) {
01671 ast_channel_lock(chan);
01672 ast_cdr_init(bridge_cdr,chan);
01673 ast_cdr_start(bridge_cdr);
01674
01675
01676 ast_cdr_merge(bridge_cdr, chan->cdr);
01677 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
01678 ast_cdr_discard(chan->cdr);
01679
01680 chan->cdr = NULL;
01681
01682 ast_channel_unlock(chan);
01683
01684
01685 ast_channel_lock(peer);
01686 ast_cdr_merge(bridge_cdr, peer->cdr);
01687 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
01688 ast_cdr_discard(peer->cdr);
01689
01690 peer->cdr = NULL;
01691 ast_channel_unlock(peer);
01692
01693 ast_channel_lock(chan);
01694 chan->cdr = bridge_cdr;
01695 ast_channel_unlock(chan);
01696
01697 } else if (chan->cdr) {
01698
01699 ast_channel_lock(chan);
01700
01701 ast_cdr_init(bridge_cdr,chan);
01702
01703 ast_cdr_merge(bridge_cdr, chan->cdr);
01704 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
01705 ast_cdr_discard(chan->cdr);
01706 chan->cdr = bridge_cdr;
01707 ast_channel_unlock(chan);
01708 } else if (peer->cdr) {
01709 ast_channel_lock(peer);
01710
01711 ast_cdr_init(bridge_cdr,peer);
01712
01713 ast_cdr_merge(bridge_cdr, peer->cdr);
01714 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
01715 ast_cdr_discard(peer->cdr);
01716 peer->cdr = NULL;
01717 peer->cdr = bridge_cdr;
01718 ast_channel_unlock(peer);
01719 } else {
01720 ast_channel_lock(chan);
01721
01722 ast_cdr_init(bridge_cdr,chan);
01723 chan->cdr = bridge_cdr;
01724 ast_channel_unlock(chan);
01725 }
01726 if (ast_strlen_zero(bridge_cdr->dstchannel)) {
01727 if (strcmp(bridge_cdr->channel, peer->name) != 0)
01728 ast_cdr_setdestchan(bridge_cdr, peer->name);
01729 else
01730 ast_cdr_setdestchan(bridge_cdr, chan->name);
01731 }
01732 }
01733 return res;
01734 }
01735
01736 static void post_manager_event(const char *s, char *parkingexten, struct ast_channel *chan)
01737 {
01738 manager_event(EVENT_FLAG_CALL, s,
01739 "Exten: %s\r\n"
01740 "Channel: %s\r\n"
01741 "CallerID: %s\r\n"
01742 "CallerIDName: %s\r\n"
01743 "Uniqueid: %s\r\n\r\n",
01744 parkingexten,
01745 chan->name,
01746 S_OR(chan->cid.cid_num, "<unknown>"),
01747 S_OR(chan->cid.cid_name, "<unknown>"),
01748 chan->uniqueid
01749 );
01750 }
01751
01752
01753 static void *do_parking_thread(void *ignore)
01754 {
01755 fd_set rfds, efds;
01756 FD_ZERO(&rfds);
01757 FD_ZERO(&efds);
01758
01759 for (;;) {
01760 struct parkeduser *pu, *pl, *pt = NULL;
01761 int ms = -1;
01762 int max = -1;
01763 fd_set nrfds, nefds;
01764 FD_ZERO(&nrfds);
01765 FD_ZERO(&nefds);
01766
01767 ast_mutex_lock(&parking_lock);
01768 pl = NULL;
01769 pu = parkinglot;
01770
01771 while (pu) {
01772 struct ast_channel *chan = pu->chan;
01773 int tms;
01774 int x;
01775 struct ast_context *con;
01776
01777 if (pu->notquiteyet) {
01778 pl = pu;
01779 pu = pu->next;
01780 continue;
01781 }
01782 tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
01783 if (tms > pu->parkingtime) {
01784 ast_indicate(chan, AST_CONTROL_UNHOLD);
01785
01786 if (pu->peername[0]) {
01787 char *peername = ast_strdupa(pu->peername);
01788 char *cp = strrchr(peername, '-');
01789 if (cp)
01790 *cp = 0;
01791 con = ast_context_find(parking_con_dial);
01792 if (!con) {
01793 con = ast_context_create(NULL, parking_con_dial, registrar);
01794 if (!con)
01795 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
01796 }
01797 if (con) {
01798 char returnexten[AST_MAX_EXTENSION];
01799 snprintf(returnexten, sizeof(returnexten), "%s|30|t", peername);
01800 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free, registrar);
01801 }
01802 set_c_e_p(chan, parking_con_dial, peername, 1);
01803 } else {
01804
01805
01806 set_c_e_p(chan, pu->context, pu->exten, pu->priority);
01807 }
01808
01809 post_manager_event("ParkedCallTimeOut", pu->parkingexten, chan);
01810
01811 if (option_verbose > 1)
01812 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);
01813
01814 if (ast_pbx_start(chan)) {
01815 ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
01816 ast_hangup(chan);
01817 }
01818
01819 if (pl)
01820 pl->next = pu->next;
01821 else
01822 parkinglot = pu->next;
01823 pt = pu;
01824 pu = pu->next;
01825 con = ast_context_find(parking_con);
01826 if (con) {
01827 if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
01828 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
01829 else
01830 notify_metermaids(pt->parkingexten, parking_con);
01831 } else
01832 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
01833 free(pt);
01834 } else {
01835 for (x = 0; x < AST_MAX_FDS; x++) {
01836 struct ast_frame *f;
01837
01838 if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
01839 continue;
01840
01841 if (FD_ISSET(chan->fds[x], &efds))
01842 ast_set_flag(chan, AST_FLAG_EXCEPTION);
01843 else
01844 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
01845 chan->fdno = x;
01846
01847
01848 f = ast_read(chan);
01849 if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
01850 if (f)
01851 ast_frfree(f);
01852 post_manager_event("ParkedCallGiveUp", pu->parkingexten, chan);
01853
01854
01855 if (option_verbose > 1)
01856 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", chan->name);
01857 ast_hangup(chan);
01858
01859 if (pl)
01860 pl->next = pu->next;
01861 else
01862 parkinglot = pu->next;
01863 pt = pu;
01864 pu = pu->next;
01865 con = ast_context_find(parking_con);
01866 if (con) {
01867 if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
01868 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
01869 else
01870 notify_metermaids(pt->parkingexten, parking_con);
01871 } else
01872 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
01873 free(pt);
01874 break;
01875 } else {
01876
01877 ast_frfree(f);
01878 if (pu->moh_trys < 3 && !chan->generatordata) {
01879 if (option_debug)
01880 ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting.\n");
01881 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
01882 S_OR(parkmohclass, NULL),
01883 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
01884 pu->moh_trys++;
01885 }
01886 goto std;
01887 }
01888
01889 }
01890 if (x >= AST_MAX_FDS) {
01891 std: for (x=0; x<AST_MAX_FDS; x++) {
01892 if (chan->fds[x] > -1) {
01893 FD_SET(chan->fds[x], &nrfds);
01894 FD_SET(chan->fds[x], &nefds);
01895 if (chan->fds[x] > max)
01896 max = chan->fds[x];
01897 }
01898 }
01899
01900 if (tms < ms || ms < 0)
01901 ms = tms;
01902 pl = pu;
01903 pu = pu->next;
01904 }
01905 }
01906 }
01907 ast_mutex_unlock(&parking_lock);
01908 rfds = nrfds;
01909 efds = nefds;
01910 {
01911 struct timeval tv = ast_samp2tv(ms, 1000);
01912
01913 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
01914 }
01915 pthread_testcancel();
01916 }
01917 return NULL;
01918 }
01919
01920
01921 static int park_call_exec(struct ast_channel *chan, void *data)
01922 {
01923
01924
01925
01926 char *orig_chan_name = ast_strdupa(chan->name);
01927 char orig_exten[AST_MAX_EXTENSION];
01928 int orig_priority = chan->priority;
01929
01930
01931
01932 int res = 0;
01933 struct ast_module_user *u;
01934
01935 u = ast_module_user_add(chan);
01936
01937 ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
01938
01939
01940
01941 strcpy(chan->exten, "s");
01942 chan->priority = 1;
01943
01944 if (chan->_state != AST_STATE_UP)
01945 res = ast_answer(chan);
01946
01947 if (!res)
01948 res = ast_safe_sleep(chan, 1000);
01949
01950 if (!res) {
01951 res = park_call_full(chan, chan, 0, NULL, orig_chan_name);
01952
01953 if (res == 1) {
01954 ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
01955 chan->priority = orig_priority;
01956 res = 0;
01957 } else if (!res)
01958 res = AST_PBX_KEEPALIVE;
01959 }
01960
01961 ast_module_user_remove(u);
01962
01963 return res;
01964 }
01965
01966
01967 static int park_exec(struct ast_channel *chan, void *data)
01968 {
01969 int res = 0;
01970 struct ast_module_user *u;
01971 struct ast_channel *peer=NULL;
01972 struct parkeduser *pu, *pl=NULL;
01973 struct ast_context *con;
01974
01975 int park;
01976 struct ast_bridge_config config;
01977
01978 if (!data) {
01979 ast_log(LOG_WARNING, "Parkedcall requires an argument (extension number)\n");
01980 return -1;
01981 }
01982
01983 u = ast_module_user_add(chan);
01984
01985 park = atoi((char *)data);
01986 ast_mutex_lock(&parking_lock);
01987 pu = parkinglot;
01988 while(pu) {
01989 if (pu->parkingnum == park) {
01990 if (pl)
01991 pl->next = pu->next;
01992 else
01993 parkinglot = pu->next;
01994 break;
01995 }
01996 pl = pu;
01997 pu = pu->next;
01998 }
01999 ast_mutex_unlock(&parking_lock);
02000 if (pu) {
02001 peer = pu->chan;
02002 con = ast_context_find(parking_con);
02003 if (con) {
02004 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
02005 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
02006 else
02007 notify_metermaids(pu->parkingexten, parking_con);
02008 } else
02009 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
02010
02011 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
02012 "Exten: %s\r\n"
02013 "Channel: %s\r\n"
02014 "From: %s\r\n"
02015 "CallerID: %s\r\n"
02016 "CallerIDName: %s\r\n"
02017 "Uniqueid: %s\r\n",
02018 pu->parkingexten, pu->chan->name, chan->name,
02019 S_OR(pu->chan->cid.cid_num, "<unknown>"),
02020 S_OR(pu->chan->cid.cid_name, "<unknown>"),
02021 pu->chan->uniqueid
02022 );
02023
02024 free(pu);
02025 }
02026
02027 if (chan->_state != AST_STATE_UP)
02028 ast_answer(chan);
02029
02030 if (peer) {
02031
02032
02033 if (!ast_strlen_zero(courtesytone)) {
02034 int error = 0;
02035 ast_indicate(peer, AST_CONTROL_UNHOLD);
02036 if (parkedplay == 0) {
02037 error = ast_stream_and_wait(chan, courtesytone, chan->language, "");
02038 } else if (parkedplay == 1) {
02039 error = ast_stream_and_wait(peer, courtesytone, chan->language, "");
02040 } else if (parkedplay == 2) {
02041 if (!ast_streamfile(chan, courtesytone, chan->language) &&
02042 !ast_streamfile(peer, courtesytone, chan->language)) {
02043
02044 res = ast_waitstream(chan, "");
02045 if (res >= 0)
02046 res = ast_waitstream(peer, "");
02047 if (res < 0)
02048 error = 1;
02049 }
02050 }
02051 if (error) {
02052 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
02053 ast_hangup(peer);
02054 ast_module_user_remove(u);
02055 return -1;
02056 }
02057 } else
02058 ast_indicate(peer, AST_CONTROL_UNHOLD);
02059
02060 res = ast_channel_make_compatible(chan, peer);
02061 if (res < 0) {
02062 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
02063 ast_hangup(peer);
02064 ast_module_user_remove(u);
02065 return -1;
02066 }
02067
02068
02069 if (option_verbose > 2)
02070 ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
02071
02072 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
02073 ast_cdr_setdestchan(chan->cdr, peer->name);
02074 memset(&config, 0, sizeof(struct ast_bridge_config));
02075 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
02076 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
02077 res = ast_bridge_call(chan, peer, &config);
02078
02079 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
02080 ast_cdr_setdestchan(chan->cdr, peer->name);
02081
02082
02083 if (res != AST_PBX_NO_HANGUP_PEER)
02084 ast_hangup(peer);
02085 ast_module_user_remove(u);
02086 return res;
02087 } else {
02088
02089 if (ast_stream_and_wait(chan, "pbx-invalidpark", chan->language, ""))
02090 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
02091 if (option_verbose > 2)
02092 ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
02093 res = -1;
02094 }
02095
02096 ast_module_user_remove(u);
02097
02098 return res;
02099 }
02100
02101 int ast_hold_call(struct ast_channel *chan, struct ast_channel *peer)
02102 {
02103
02104
02105 struct holdeduser *pu;
02106 pu = malloc(sizeof(struct holdeduser));
02107 if (pu) {
02108 memset(pu, 0, sizeof(pu));
02109 ast_mutex_lock(&holding_lock);
02110 chan->appl = "Holded Call";
02111 chan->data = NULL;
02112
02113 pu->chan = chan;
02114 strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid));
02115 strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer));
02116
02117 ast_moh_start(pu->chan, NULL, NULL);
02118 gettimeofday(&pu->start, NULL);
02119 pu->next = holdlist;
02120 holdlist = pu;
02121 ast_mutex_unlock(&holding_lock);
02122
02123 pthread_kill(holding_thread, SIGURG);
02124
02125 manager_event(EVENT_FLAG_CALL, "HoldedCall",
02126 "Channel1: %s\r\n"
02127 "Channel2: %s\r\n"
02128 "Uniqueid1: %s\r\n"
02129 "Uniqueid2: %s\r\n"
02130 ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid);
02131
02132 } else {
02133 ast_log(LOG_WARNING, "Out of memory\n");
02134 return -1;
02135 }
02136 return 0;
02137 }
02138
02139 int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *peer)
02140 {
02141 struct ast_channel *chan;
02142 struct ast_frame *f;
02143
02144 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Onhold/%s",rchan->name);
02145 if (chan) {
02146
02147 ast_string_field_build(chan, name, "Onhold/%s",rchan->name);
02148
02149 chan->readformat = rchan->readformat;
02150 chan->writeformat = rchan->writeformat;
02151 ast_channel_masquerade(chan, rchan);
02152
02153 strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
02154 strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
02155 chan->priority = rchan->priority;
02156
02157 ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
02158
02159 f = ast_read(chan);
02160 if (f)
02161 ast_frfree(f);
02162 ast_hold_call(chan, peer);
02163 return -1;
02164 } else {
02165 ast_log(LOG_WARNING, "Unable to create holded channel\n");
02166 return -1;
02167 }
02168 return 0;
02169 }
02170
02171 int ast_retrieve_call(struct ast_channel *chan, char *uniqueid)
02172 {
02173 int res=-1, dres=-1;
02174 struct ast_channel *peer=NULL;
02175 struct ast_bridge_config config;
02176
02177 peer = ast_get_holded_call(uniqueid);
02178
02179
02180 if (chan->_state != AST_STATE_UP) {
02181 ast_answer(chan);
02182 }
02183
02184 if (peer) {
02185 ast_mutex_unlock(&peer->lock);
02186 ast_moh_stop(peer);
02187 res = ast_channel_make_compatible(chan, peer);
02188 if (res < 0) {
02189 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
02190 ast_hangup(peer);
02191 return -1;
02192 }
02193
02194
02195 if (option_verbose > 2)
02196 ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name);
02197
02198 memset(&config,0,sizeof(struct ast_bridge_config));
02199 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
02200 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
02201 config.timelimit = 0;
02202 config.play_warning = 0;
02203 config.warning_freq = 0;
02204 config.warning_sound=NULL;
02205 res = ast_bridge_call(chan,peer,&config);
02206
02207
02208 if (res != AST_PBX_NO_HANGUP_PEER)
02209 ast_hangup(peer);
02210 return res;
02211 } else {
02212
02213 dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
02214 if (!dres)
02215 dres = ast_waitstream(chan, "");
02216 else {
02217 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
02218 dres = 0;
02219 }
02220 }
02221 return res;
02222 }
02223
02224 int ast_retrieve_call_to_death(char *uniqueid)
02225 {
02226 int res=-1;
02227 struct ast_channel *peer=NULL;
02228
02229 peer = ast_get_holded_call(uniqueid);
02230
02231 if (peer) {
02232 res=0;
02233 if (option_verbose > 2)
02234 ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
02235 ast_mutex_unlock(&peer->lock);
02236 ast_hangup(peer);
02237 } else {
02238 ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid);
02239 }
02240 return res;
02241 }
02242
02243 struct ast_channel *ast_get_holded_call(char *uniqueid)
02244 {
02245 int res=-1;
02246 struct ast_channel *peer=NULL;
02247 struct holdeduser *pu, *pl=NULL;
02248
02249 ast_mutex_lock(&holding_lock);
02250 pu = holdlist;
02251 while(pu) {
02252 if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) {
02253 if (pl)
02254 pl->next = pu->next;
02255 else
02256 holdlist = pu->next;
02257 break;
02258 }
02259 pl = pu;
02260 pu = pu->next;
02261 }
02262 ast_mutex_unlock(&holding_lock);
02263 if (pu) {
02264 peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid);
02265 free(pu);
02266 if (peer) {
02267 res=0;
02268 if (option_verbose > 2)
02269 ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
02270 ast_moh_stop(peer);
02271 return peer;
02272 } else {
02273 if (option_verbose > 2)
02274 ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid);
02275 return NULL;
02276 }
02277 } else {
02278 ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid);
02279 }
02280 return NULL;
02281 }
02282
02283
02284 static void *do_holding_thread(void *ignore)
02285 {
02286 int ms, tms, max;
02287 struct holdeduser *pu, *pl, *pt = NULL;
02288 struct timeval tv;
02289 struct ast_frame *f;
02290 int x;
02291 fd_set rfds, efds;
02292 fd_set nrfds, nefds;
02293 FD_ZERO(&rfds);
02294 FD_ZERO(&efds);
02295 for (;;) {
02296 ms = -1;
02297 max = -1;
02298 ast_mutex_lock(&holding_lock);
02299 pl = NULL;
02300 pu = holdlist;
02301 gettimeofday(&tv, NULL);
02302 FD_ZERO(&nrfds);
02303 FD_ZERO(&nefds);
02304 while(pu) {
02305 tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
02306 for (x=0;x<AST_MAX_FDS;x++) {
02307 if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
02308 if (FD_ISSET(pu->chan->fds[x], &efds))
02309 ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
02310 else
02311 ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
02312 pu->chan->fdno = x;
02313
02314 f = ast_read(pu->chan);
02315 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
02316
02317 if (option_verbose > 1)
02318 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being onhold\n", pu->chan->name);
02319 ast_hangup(pu->chan);
02320
02321
02322
02323 if (pl)
02324 pl->next = pu->next;
02325 else
02326 holdlist = pu->next;
02327 pt = pu;
02328 pu = pu->next;
02329 free(pt);
02330 break;
02331 } else {
02332
02333 ast_frfree(f);
02334 goto std;
02335 }
02336 }
02337 }
02338 if (x >= AST_MAX_FDS) {
02339 std: for (x=0;x<AST_MAX_FDS;x++) {
02340
02341 if (pu->chan->fds[x] > -1) {
02342 FD_SET(pu->chan->fds[x], &nrfds);
02343 FD_SET(pu->chan->fds[x], &nefds);
02344 if (pu->chan->fds[x] > max)
02345 max = pu->chan->fds[x];
02346 }
02347 }
02348
02349 if ((tms < ms) || (ms < 0))
02350 ms = tms;
02351 pl = pu;
02352 pu = pu->next;
02353 }
02354 }
02355 ast_mutex_unlock(&holding_lock);
02356 rfds = nrfds;
02357 efds = nefds;
02358 tv.tv_sec = ms / 1000;
02359 tv.tv_usec = (ms % 1000) * 1000;
02360
02361 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
02362 pthread_testcancel();
02363 }
02364 return NULL;
02365 }
02366
02367 static int retrieve_call_exec(struct ast_channel *chan, void *data) {
02368 int res=0;
02369 struct ast_module_user *u;
02370 char *uniqueid = (char *)data;
02371 u = ast_module_user_add(chan);
02372 res = ast_retrieve_call(chan, uniqueid);
02373 ast_module_user_remove(u);
02374 return res;
02375 }
02376
02377 static int handle_showfeatures(int fd, int argc, char *argv[])
02378 {
02379 int i;
02380 struct ast_call_feature *feature;
02381 char format[] = "%-25s %-7s %-7s\n";
02382
02383 ast_cli(fd, format, "Builtin Feature", "Default", "Current");
02384 ast_cli(fd, format, "---------------", "-------", "-------");
02385
02386 ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext());
02387
02388 ast_rwlock_rdlock(&features_lock);
02389 for (i = 0; i < FEATURES_COUNT; i++)
02390 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
02391 ast_rwlock_unlock(&features_lock);
02392
02393 ast_cli(fd, "\n");
02394 ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
02395 ast_cli(fd, format, "---------------", "-------", "-------");
02396 if (AST_LIST_EMPTY(&feature_list))
02397 ast_cli(fd, "(none)\n");
02398 else {
02399 AST_LIST_LOCK(&feature_list);
02400 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry)
02401 ast_cli(fd, format, feature->sname, "no def", feature->exten);
02402 AST_LIST_UNLOCK(&feature_list);
02403 }
02404 ast_cli(fd, "\nCall parking\n");
02405 ast_cli(fd, "------------\n");
02406 ast_cli(fd,"%-20s: %s\n", "Parking extension", parking_ext);
02407 ast_cli(fd,"%-20s: %s\n", "Parking context", parking_con);
02408 ast_cli(fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
02409 ast_cli(fd,"\n");
02410
02411 return RESULT_SUCCESS;
02412 }
02413
02414 static char mandescr_bridge[] =
02415 "Description: Bridge together two channels already in the PBX\n"
02416 "Variables: ( Headers marked with * are required )\n"
02417 " *Channel1: Channel to Bridge to Channel2\n"
02418 " *Channel2: Channel to Bridge to Channel1\n"
02419 " Tone: (Yes|No) Play courtesy tone to Channel 2\n"
02420 "\n";
02421
02422 static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
02423 {
02424 ast_moh_stop(chan);
02425 ast_mutex_lock(&chan->lock);
02426 ast_setstate(tmpchan, chan->_state);
02427 tmpchan->readformat = chan->readformat;
02428 tmpchan->writeformat = chan->writeformat;
02429 ast_channel_masquerade(tmpchan, chan);
02430 ast_mutex_lock(&tmpchan->lock);
02431 ast_do_masquerade(tmpchan);
02432
02433 ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
02434 ast_mutex_unlock(&tmpchan->lock);
02435 ast_mutex_unlock(&chan->lock);
02436 }
02437
02438 static int action_bridge(struct mansession *s, const struct message *m)
02439 {
02440 const char *channela = astman_get_header(m, "Channel1");
02441 const char *channelb = astman_get_header(m, "Channel2");
02442 const char *playtone = astman_get_header(m, "Tone");
02443 struct ast_channel *chana = NULL, *chanb = NULL;
02444 struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
02445 struct ast_bridge_thread_obj *tobj = NULL;
02446
02447
02448 if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) {
02449 chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
02450 chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
02451 if (chana)
02452 ast_mutex_unlock(&chana->lock);
02453 if (chanb)
02454 ast_mutex_unlock(&chanb->lock);
02455
02456
02457 if (!chana) {
02458 char buf[256];
02459 snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
02460 astman_send_error(s, m, buf);
02461 return 0;
02462 }
02463 if (!chanb) {
02464 char buf[256];
02465 snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
02466 astman_send_error(s, m, buf);
02467 return 0;
02468 }
02469 } else {
02470 astman_send_error(s, m, "Missing channel parameter in request");
02471 return 0;
02472 }
02473
02474
02475 if (chana->_state != AST_STATE_UP)
02476 ast_answer(chana);
02477 if (chanb->_state != AST_STATE_UP)
02478 ast_answer(chanb);
02479
02480
02481 if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
02482 NULL, NULL, 0, "Bridge/%s", chana->name))) {
02483 astman_send_error(s, m, "Unable to create temporary channel!");
02484 return 1;
02485 }
02486
02487 if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
02488 NULL, NULL, 0, "Bridge/%s", chanb->name))) {
02489 astman_send_error(s, m, "Unable to create temporary channels!");
02490 ast_channel_free(tmpchana);
02491 return 1;
02492 }
02493
02494 do_bridge_masquerade(chana, tmpchana);
02495 do_bridge_masquerade(chanb, tmpchanb);
02496
02497
02498 if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
02499 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
02500 astman_send_error(s, m, "Could not make channels compatible for manager bridge");
02501 ast_hangup(tmpchana);
02502 ast_hangup(tmpchanb);
02503 return 1;
02504 }
02505
02506
02507 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
02508 ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
02509 astman_send_error(s, m, "Unable to spawn a new bridge thread");
02510 ast_hangup(tmpchana);
02511 ast_hangup(tmpchanb);
02512 return 1;
02513 }
02514
02515 tobj->chan = tmpchana;
02516 tobj->peer = tmpchanb;
02517 tobj->return_to_pbx = 1;
02518
02519 if (ast_true(playtone)) {
02520 if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
02521 if (ast_waitstream(tmpchanb, "") < 0)
02522 ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
02523 }
02524 }
02525
02526 ast_bridge_call_thread_launch(tobj);
02527
02528 astman_send_ack(s, m, "Launched bridge thread with success");
02529
02530 return 0;
02531 }
02532
02533 static char showfeatures_help[] =
02534 "Usage: feature list\n"
02535 " Lists currently configured features.\n";
02536
02537 static int handle_parkedcalls(int fd, int argc, char *argv[])
02538 {
02539 struct parkeduser *cur;
02540 int numparked = 0;
02541
02542 ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
02543 , "Context", "Extension", "Pri", "Timeout");
02544
02545 ast_mutex_lock(&parking_lock);
02546
02547 for (cur = parkinglot; cur; cur = cur->next) {
02548 ast_cli(fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
02549 ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
02550 ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
02551
02552 numparked++;
02553 }
02554 ast_mutex_unlock(&parking_lock);
02555 ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : "");
02556
02557
02558 return RESULT_SUCCESS;
02559 }
02560
02561 static char showparked_help[] =
02562 "Usage: show parkedcalls\n"
02563 " Lists currently parked calls.\n";
02564
02565 static struct ast_cli_entry cli_show_features_deprecated = {
02566 { "show", "features", NULL },
02567 handle_showfeatures, NULL,
02568 NULL };
02569
02570 static char showautoanswer_help[] =
02571 "Usage: show autoanswer\n"
02572 " Lists currently logged in autoanswer users.\n";
02573
02574
02575
02576 static int manager_parking_status( struct mansession *s, const struct message *m)
02577 {
02578 struct parkeduser *cur;
02579 const char *id = astman_get_header(m, "ActionID");
02580 char idText[256] = "";
02581
02582 if (!ast_strlen_zero(id))
02583 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
02584
02585 astman_send_ack(s, m, "Parked calls will follow");
02586
02587 ast_mutex_lock(&parking_lock);
02588
02589 for (cur = parkinglot; cur; cur = cur->next) {
02590 astman_append(s, "Event: ParkedCall\r\n"
02591 "Exten: %d\r\n"
02592 "Channel: %s\r\n"
02593 "From: %s\r\n"
02594 "Timeout: %ld\r\n"
02595 "CallerID: %s\r\n"
02596 "CallerIDName: %s\r\n"
02597 "Uniqueid: %s\r\n\r\n"
02598 "%s"
02599 "\r\n",
02600 cur->parkingnum, cur->chan->name, cur->peername,
02601 (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
02602 S_OR(cur->chan->cid.cid_num, ""),
02603 S_OR(cur->chan->cid.cid_name, ""), cur->chan->uniqueid,
02604 idText);
02605 }
02606
02607 astman_append(s,
02608 "Event: ParkedCallsComplete\r\n"
02609 "%s"
02610 "\r\n",idText);
02611
02612 ast_mutex_unlock(&parking_lock);
02613
02614 return RESULT_SUCCESS;
02615 }
02616
02617 static char mandescr_park[] =
02618 "Description: Park a channel.\n"
02619 "Variables: (Names marked with * are required)\n"
02620 " *Channel: Channel name to park\n"
02621 " *Channel2: Channel to announce park info to (and return to if timeout)\n"
02622 " Timeout: Number of milliseconds to wait before callback.\n";
02623
02624 static int manager_park(struct mansession *s, const struct message *m)
02625 {
02626 const char *channel = astman_get_header(m, "Channel");
02627 const char *channel2 = astman_get_header(m, "Channel2");
02628 const char *timeout = astman_get_header(m, "Timeout");
02629 char buf[BUFSIZ];
02630 int to = 0;
02631 int res = 0;
02632 int parkExt = 0;
02633 struct ast_channel *ch1, *ch2;
02634
02635 if (ast_strlen_zero(channel)) {
02636 astman_send_error(s, m, "Channel not specified");
02637 return 0;
02638 }
02639
02640 if (ast_strlen_zero(channel2)) {
02641 astman_send_error(s, m, "Channel2 not specified");
02642 return 0;
02643 }
02644
02645 ch1 = ast_get_channel_by_name_locked(channel);
02646 if (!ch1) {
02647 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
02648 astman_send_error(s, m, buf);
02649 return 0;
02650 }
02651
02652 ch2 = ast_get_channel_by_name_locked(channel2);
02653 if (!ch2) {
02654 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
02655 astman_send_error(s, m, buf);
02656 ast_channel_unlock(ch1);
02657 return 0;
02658 }
02659
02660 if (!ast_strlen_zero(timeout)) {
02661 sscanf(timeout, "%d", &to);
02662 }
02663
02664 res = ast_masq_park_call(ch1, ch2, to, &parkExt);
02665 if (!res) {
02666 ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
02667 astman_send_ack(s, m, "Park successful");
02668 } else {
02669 astman_send_error(s, m, "Park failure");
02670 }
02671
02672 ast_channel_unlock(ch1);
02673 ast_channel_unlock(ch2);
02674
02675 return 0;
02676 }
02677
02678 static int handle_autoanswer(int fd, int argc, char *argv[])
02679 {
02680 struct aauser *cur;
02681
02682 ast_cli(fd, "%25s %10s %15s \n", "Channel"
02683 , "Extension", "Context");
02684
02685 ast_mutex_lock(&autoanswer_lock);
02686
02687 cur=aalot;
02688 while(cur) {
02689 ast_cli(fd, "%25s %10s %15s\n",cur->chan->name, cur->exten, cur->context);
02690
02691 cur = cur->next;
02692 }
02693
02694 ast_mutex_unlock(&autoanswer_lock);
02695
02696 return RESULT_SUCCESS;
02697 }
02698
02699 static struct ast_cli_entry cli_features[] = {
02700 { { "feature", "list", NULL },
02701 handle_showfeatures, "Lists configured features",
02702 showfeatures_help, NULL, &cli_show_features_deprecated },
02703
02704 { { "show", "parkedcalls", NULL },
02705 handle_parkedcalls, "Lists parked calls",
02706 showparked_help },
02707
02708 { { "show", "autoanswer", NULL },
02709 handle_autoanswer, "Lists autoanswer users",
02710 showautoanswer_help },
02711 };
02712 int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data)
02713 {
02714 struct ast_channel *chan;
02715 struct ast_frame *f;
02716
02717 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Autoanswer/%s", rchan->name);
02718 if (chan) {
02719
02720 ast_string_field_build(chan, name, "Autoanswer/%s",rchan->name);
02721
02722 chan->readformat = rchan->readformat;
02723 chan->writeformat = rchan->writeformat;
02724 ast_channel_masquerade(chan, rchan);
02725
02726 strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
02727 strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
02728 chan->priority = rchan->priority;
02729
02730 ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
02731
02732 f = ast_read(chan);
02733 if (f)
02734 ast_frfree(f);
02735 ast_autoanswer_login(chan, data);
02736 } else {
02737 ast_log(LOG_WARNING, "Unable to create aa channel\n");
02738 return -1;
02739 }
02740 return 0;
02741 }
02742
02743 static int autoanswer_login_exec(struct ast_channel *chan, void *data)
02744 {
02745 int res=0;
02746 struct ast_module_user *u;
02747
02748 u = ast_module_user_add(chan);
02749 if (!data) {
02750 ast_log(LOG_WARNING, "AutoanswerLogin requires an argument (extension number)\n");
02751 return -1;
02752 }
02753 res = ast_masq_autoanswer_login(chan, data);
02754 ast_module_user_remove(u);
02755 return res;
02756 }
02757
02758 int ast_autoanswer_login(struct ast_channel *chan, void *data)
02759 {
02760
02761
02762 struct ast_context *con;
02763 char exten[AST_MAX_EXTENSION];
02764 struct aauser *pu,*pl = NULL;
02765 char *s, *stringp, *aacontext, *aaexten = NULL;
02766
02767 s = ast_strdupa((void *) data);
02768 stringp=s;
02769 aacontext = strsep(&stringp, "|");
02770 aaexten = strsep(&stringp, "|");
02771 if (!aaexten) {
02772 aaexten = aacontext;
02773 aacontext = NULL;
02774 }
02775 if (!aaexten) {
02776 ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
02777 return -1;
02778 } else {
02779 if (!aacontext) {
02780 aacontext = "default";
02781 }
02782 }
02783
02784 ast_mutex_lock(&autoanswer_lock);
02785 pu = aalot;
02786 while(pu) {
02787 if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
02788 if (pl)
02789 pl->next = pu->next;
02790 else
02791 aalot = pu->next;
02792 break;
02793 }
02794 pl = pu;
02795 pu = pu->next;
02796 }
02797 ast_mutex_unlock(&autoanswer_lock);
02798 if (pu) {
02799 ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context);
02800 manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
02801 "Channel: %s\r\n"
02802 "Uniqueid: %s\r\n"
02803 "Context: %s\r\n"
02804 "Exten: %s\r\n"
02805 ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
02806 ast_hangup(pu->chan);
02807 free(pu);
02808 }
02809 pu = malloc(sizeof(struct aauser));
02810 if (pu) {
02811 memset(pu, 0, sizeof(pu));
02812 ast_mutex_lock(&autoanswer_lock);
02813 chan->appl = "Autoanswer";
02814 chan->data = NULL;
02815
02816 pu->chan = chan;
02817 if (chan->_state != AST_STATE_UP) {
02818 ast_answer(chan);
02819 }
02820
02821
02822 ast_moh_start(pu->chan, NULL, NULL);
02823 gettimeofday(&pu->start, NULL);
02824 strncpy(pu->exten, aaexten, sizeof(pu->exten)-1);
02825 strncpy(pu->context, aacontext, sizeof(pu->exten)-1);
02826 pu->next = aalot;
02827 aalot = pu;
02828 con = ast_context_find(aacontext);
02829 if (!con) {
02830 con = ast_context_create(NULL,aacontext, registrar);
02831 if (!con) {
02832 ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext);
02833 }
02834 }
02835 if (con) {
02836 snprintf(exten, sizeof(exten), "%s", aaexten);
02837 ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar);
02838 }
02839
02840 ast_mutex_unlock(&autoanswer_lock);
02841
02842 pthread_kill(autoanswer_thread, SIGURG);
02843 if (option_verbose > 1)
02844 ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context);
02845 manager_event(EVENT_FLAG_CALL, "AutoanswerLogin",
02846 "Channel: %s\r\n"
02847 "Uniqueid: %s\r\n"
02848 "Context: %s\r\n"
02849 "Exten: %s\r\n"
02850 ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
02851
02852 return 0;
02853 } else {
02854 ast_log(LOG_WARNING, "Out of memory\n");
02855 return -1;
02856 }
02857 return 0;
02858 }
02859
02860 static void autoanswer_reregister_extensions(void)
02861 {
02862 struct aauser *cur;
02863 struct ast_context *con;
02864 char exten[AST_MAX_EXTENSION];
02865 char args[AST_MAX_EXTENSION];
02866
02867 ast_mutex_lock(&autoanswer_lock);
02868
02869 cur=aalot;
02870 while(cur) {
02871 con = ast_context_find(cur->context);
02872 if (!con) {
02873 con = ast_context_create(NULL,cur->context, registrar);
02874 if (!con) {
02875 ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", cur->context);
02876 }
02877 }
02878 if (con) {
02879 snprintf(exten, sizeof(exten), "%s", cur->exten);
02880 snprintf(args, sizeof(args), "%s|%s", cur->context, cur->exten);
02881 ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)args), free, registrar);
02882 }
02883 cur = cur->next;
02884 }
02885
02886 ast_mutex_unlock(&autoanswer_lock);
02887 }
02888 static void *do_autoanswer_thread(void *ignore)
02889 {
02890 int ms, tms, max;
02891 struct ast_context *con;
02892 char exten[AST_MAX_EXTENSION];
02893 struct aauser *pu, *pl, *pt = NULL;
02894 struct timeval tv;
02895 struct ast_frame *f;
02896 int x;
02897 fd_set rfds, efds;
02898 fd_set nrfds, nefds;
02899 FD_ZERO(&rfds);
02900 FD_ZERO(&efds);
02901 for (;;) {
02902 ms = -1;
02903 max = -1;
02904 ast_mutex_lock(&autoanswer_lock);
02905 pl = NULL;
02906 pu = aalot;
02907 gettimeofday(&tv, NULL);
02908 FD_ZERO(&nrfds);
02909 FD_ZERO(&nefds);
02910 while(pu) {
02911 tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
02912 for (x=0;x<AST_MAX_FDS;x++) {
02913 if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
02914 if (FD_ISSET(pu->chan->fds[x], &efds))
02915 ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
02916 else
02917 ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
02918 pu->chan->fdno = x;
02919
02920 f = ast_read(pu->chan);
02921 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
02922
02923 if (option_verbose > 1)
02924 ast_verbose(VERBOSE_PREFIX_2 "%s logged out of autoanswer app\n", pu->chan->name);
02925 manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
02926 "Channel: %s\r\n"
02927 "Uniqueid: %s\r\n"
02928 "Context: %s\r\n"
02929 "Exten: %s\r\n"
02930 ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
02931 ast_hangup(pu->chan);
02932 con = ast_context_find(pu->context);
02933 if (con) {
02934 snprintf(exten, sizeof(exten), "%s", pu->exten);
02935 if (ast_context_remove_extension2(con, exten, 1, registrar))
02936 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
02937 } else {
02938 ast_log(LOG_WARNING, "Whoa, no %s context?\n", pu->exten);
02939 }
02940
02941 if (pl)
02942 pl->next = pu->next;
02943 else
02944 aalot = pu->next;
02945 pt = pu;
02946 pu = pu->next;
02947 free(pt);
02948 break;
02949 } else {
02950
02951 ast_frfree(f);
02952 goto std;
02953 }
02954 }
02955 }
02956 if (x >= AST_MAX_FDS) {
02957 std: for (x=0;x<AST_MAX_FDS;x++) {
02958
02959 if (pu->chan->fds[x] > -1) {
02960 FD_SET(pu->chan->fds[x], &nrfds);
02961 FD_SET(pu->chan->fds[x], &nefds);
02962 if (pu->chan->fds[x] > max)
02963 max = pu->chan->fds[x];
02964 }
02965 }
02966
02967 if ((tms < ms) || (ms < 0))
02968 ms = tms;
02969 pl = pu;
02970 pu = pu->next;
02971 }
02972 }
02973 ast_mutex_unlock(&autoanswer_lock);
02974 rfds = nrfds;
02975 efds = nefds;
02976 tv.tv_sec = ms / 1000;
02977 tv.tv_usec = (ms % 1000) * 1000;
02978
02979 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
02980 pthread_testcancel();
02981 }
02982 return NULL;
02983 }
02984
02985 static int autoanswer_exec(struct ast_channel *chan, void *data)
02986 {
02987 int res=0;
02988 struct ast_channel *peer=NULL;
02989 struct aauser *pu, *pl=NULL;
02990 struct ast_bridge_config config;
02991 char *s, *stringp, *aacontext, *aaexten = NULL;
02992 char datastring[80];
02993 struct ast_module_user *u;
02994
02995
02996 if (!data) {
02997 ast_log(LOG_WARNING, "Autoanswer requires an argument (extension number)\n");
02998 return -1;
02999 }
03000 s = ast_strdupa((void *) data);
03001 stringp=s;
03002 aacontext = strsep(&stringp, "|");
03003 aaexten = strsep(&stringp, "|");
03004 if (!aaexten) {
03005 aaexten = aacontext;
03006 aacontext = NULL;
03007 }
03008 if (!aaexten) {
03009 ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
03010 return -1;
03011 } else {
03012 if (!aacontext) {
03013 aacontext = "default";
03014 }
03015 }
03016
03017 u = ast_module_user_add(chan);
03018 ast_mutex_lock(&autoanswer_lock);
03019 pu = aalot;
03020 while(pu) {
03021 if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
03022 if (pl)
03023 pl->next = pu->next;
03024 else
03025 aalot = pu->next;
03026 break;
03027 }
03028 pl = pu;
03029 pu = pu->next;
03030 }
03031 ast_mutex_unlock(&autoanswer_lock);
03032 if (pu) {
03033 peer = pu->chan;
03034 free(pu);
03035 pu = NULL;
03036 }
03037
03038 if (chan->_state != AST_STATE_UP) {
03039 ast_answer(chan);
03040 }
03041
03042 if (peer) {
03043 ast_moh_stop(peer);
03044
03045 if (!ast_strlen_zero(courtesytone)) {
03046 if (!ast_streamfile(peer, courtesytone, peer->language)) {
03047 if (ast_waitstream(peer, "") < 0) {
03048 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
03049 ast_hangup(peer);
03050 return -1;
03051 }
03052 }
03053 }
03054
03055 res = ast_channel_make_compatible(chan, peer);
03056 if (res < 0) {
03057 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
03058 ast_hangup(peer);
03059 return -1;
03060 }
03061
03062
03063 if (option_verbose > 2)
03064 ast_verbose(VERBOSE_PREFIX_3 "Channel %s autoanswered %s\n", peer->name, chan->name);
03065 manager_event(EVENT_FLAG_CALL, "Autoanswer",
03066 "Channel: %s\r\n"
03067 "Uniqueid: %s\r\n"
03068 "Channel2: %s\r\n"
03069 "Uniqueid2: %s\r\n"
03070 "Context: %s\r\n"
03071 "Exten: %s\r\n"
03072 ,chan->name, chan->uniqueid, peer->name, peer->uniqueid, aacontext, aaexten);
03073
03074
03075 memset(&config,0,sizeof(struct ast_bridge_config));
03076 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
03077 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
03078 config.timelimit = 0;
03079 config.play_warning = 0;
03080 config.warning_freq = 0;
03081 config.warning_sound=NULL;
03082 res = ast_bridge_call(chan,peer,&config);
03083
03084 if (option_verbose > 2)
03085 ast_verbose(VERBOSE_PREFIX_3 "returning from bridge %s\n", peer->name);
03086
03087 snprintf(datastring, sizeof(datastring) - 1, "%s|%s", aacontext, aaexten);
03088 ast_autoanswer_login(peer, datastring);
03089 return res;
03090 } else {
03091 if (option_verbose > 2)
03092 ast_verbose(VERBOSE_PREFIX_3 "Nobody logged in for autoanswer %s@%s\n", aaexten, aacontext);
03093 res = -1;
03094 }
03095 ast_module_user_remove(u);
03096 return res;
03097 }
03098
03099
03100 int ast_pickup_call(struct ast_channel *chan)
03101 {
03102 struct ast_channel *cur = NULL;
03103 int res = -1;
03104
03105 while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
03106 if (!cur->pbx &&
03107 (cur != chan) &&
03108 (chan->pickupgroup & cur->callgroup) &&
03109 ((cur->_state == AST_STATE_RINGING) ||
03110 (cur->_state == AST_STATE_RING))) {
03111 break;
03112 }
03113 ast_channel_unlock(cur);
03114 }
03115 if (cur) {
03116 if (option_debug)
03117 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
03118 res = ast_answer(chan);
03119 if (res)
03120 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
03121 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
03122 if (res)
03123 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
03124 res = ast_channel_masquerade(cur, chan);
03125 if (res)
03126 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);
03127 ast_channel_unlock(cur);
03128 } else {
03129 if (option_debug)
03130 ast_log(LOG_DEBUG, "No call pickup possible...\n");
03131 }
03132 return res;
03133 }
03134
03135
03136 static void park_add_hints(char *context, int start, int stop)
03137 {
03138 int numext;
03139 char device[AST_MAX_EXTENSION];
03140 char exten[10];
03141
03142 for (numext = start; numext <= stop; numext++) {
03143 snprintf(exten, sizeof(exten), "%d", numext);
03144 snprintf(device, sizeof(device), "park:%s@%s", exten, context);
03145 ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
03146 }
03147 }
03148
03149
03150 static int load_config(void)
03151 {
03152 int start = 0, end = 0;
03153 int res;
03154 struct ast_context *con = NULL;
03155 struct ast_config *cfg = NULL;
03156 struct ast_variable *var = NULL;
03157 char old_parking_ext[AST_MAX_EXTENSION];
03158 char old_parking_con[AST_MAX_EXTENSION] = "";
03159
03160 if (!ast_strlen_zero(parking_con)) {
03161 strcpy(old_parking_ext, parking_ext);
03162 strcpy(old_parking_con, parking_con);
03163 }
03164
03165
03166 strcpy(parking_con, "parkedcalls");
03167 strcpy(parking_con_dial, "park-dial");
03168 strcpy(parking_ext, "700");
03169 strcpy(pickup_ext, "*8");
03170 strcpy(parkmohclass, "default");
03171 courtesytone[0] = '\0';
03172 strcpy(xfersound, "beep");
03173 strcpy(xferfailsound, "pbx-invalid");
03174 parking_start = 701;
03175 parking_stop = 750;
03176 parkfindnext = 0;
03177 adsipark = 0;
03178 parkaddhints = 0;
03179
03180 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
03181 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
03182 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
03183
03184 cfg = ast_config_load("features.conf");
03185 if (!cfg) {
03186 ast_log(LOG_WARNING,"Could not load features.conf\n");
03187 return AST_MODULE_LOAD_DECLINE;
03188 }
03189 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
03190 if (!strcasecmp(var->name, "parkext")) {
03191 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
03192 } else if (!strcasecmp(var->name, "context")) {
03193 ast_copy_string(parking_con, var->value, sizeof(parking_con));
03194 } else if (!strcasecmp(var->name, "parkingtime")) {
03195 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
03196 ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
03197 parkingtime = DEFAULT_PARK_TIME;
03198 } else
03199 parkingtime = parkingtime * 1000;
03200 } else if (!strcasecmp(var->name, "parkpos")) {
03201 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
03202 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);
03203 } else {
03204 parking_start = start;
03205 parking_stop = end;
03206 }
03207 } else if (!strcasecmp(var->name, "findslot")) {
03208 parkfindnext = (!strcasecmp(var->value, "next"));
03209 } else if (!strcasecmp(var->name, "parkinghints")) {
03210 parkaddhints = ast_true(var->value);
03211 } else if (!strcasecmp(var->name, "adsipark")) {
03212 adsipark = ast_true(var->value);
03213 } else if (!strcasecmp(var->name, "transferdigittimeout")) {
03214 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
03215 ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
03216 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
03217 } else
03218 transferdigittimeout = transferdigittimeout * 1000;
03219 } else if (!strcasecmp(var->name, "featuredigittimeout")) {
03220 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
03221 ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
03222 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
03223 }
03224 } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
03225 if ((sscanf(var->value, "%d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
03226 ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
03227 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
03228 } else
03229 atxfernoanswertimeout = atxfernoanswertimeout * 1000;
03230 } else if (!strcasecmp(var->name, "courtesytone")) {
03231 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
03232 } else if (!strcasecmp(var->name, "parkedplay")) {
03233 if (!strcasecmp(var->value, "both"))
03234 parkedplay = 2;
03235 else if (!strcasecmp(var->value, "parked"))
03236 parkedplay = 1;
03237 else
03238 parkedplay = 0;
03239 } else if (!strcasecmp(var->name, "xfersound")) {
03240 ast_copy_string(xfersound, var->value, sizeof(xfersound));
03241 } else if (!strcasecmp(var->name, "xferfailsound")) {
03242 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
03243 } else if (!strcasecmp(var->name, "pickupexten")) {
03244 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
03245 } else if (!strcasecmp(var->name, "parkedmusicclass")) {
03246 ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
03247 }
03248 }
03249
03250 unmap_features();
03251 for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
03252 if (remap_feature(var->name, var->value))
03253 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
03254 }
03255
03256
03257 ast_unregister_features();
03258 for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
03259 char *tmp_val = ast_strdupa(var->value);
03260 char *exten, *activateon, *activatedby, *app, *app_args, *moh_class;
03261 struct ast_call_feature *feature;
03262
03263
03264
03265
03266
03267 exten = strsep(&tmp_val,",");
03268 activatedby = strsep(&tmp_val,",");
03269 app = strsep(&tmp_val,",");
03270 app_args = strsep(&tmp_val,",");
03271 moh_class = strsep(&tmp_val,",");
03272
03273 activateon = strsep(&activatedby, "/");
03274
03275
03276 if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
03277 ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
03278 app, exten, activateon, var->name);
03279 continue;
03280 }
03281
03282 AST_LIST_LOCK(&feature_list);
03283 if ((feature = find_dynamic_feature(var->name))) {
03284 AST_LIST_UNLOCK(&feature_list);
03285 ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
03286 continue;
03287 }
03288 AST_LIST_UNLOCK(&feature_list);
03289
03290 if (!(feature = ast_calloc(1, sizeof(*feature))))
03291 continue;
03292
03293 ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
03294 ast_copy_string(feature->app, app, FEATURE_APP_LEN);
03295 ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
03296
03297 if (app_args)
03298 ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
03299
03300 if (moh_class)
03301 ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
03302
03303 ast_copy_string(feature->exten, exten, sizeof(feature->exten));
03304 feature->operation = feature_exec_app;
03305 ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
03306
03307
03308 if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
03309 ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
03310 else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
03311 ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
03312 else {
03313 ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
03314 " must be 'self', or 'peer'\n", var->name);
03315 continue;
03316 }
03317
03318 if (ast_strlen_zero(activatedby))
03319 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
03320 else if (!strcasecmp(activatedby, "caller"))
03321 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
03322 else if (!strcasecmp(activatedby, "callee"))
03323 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
03324 else if (!strcasecmp(activatedby, "both"))
03325 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
03326 else {
03327 ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
03328 " must be 'caller', or 'callee', or 'both'\n", var->name);
03329 continue;
03330 }
03331
03332 ast_register_feature(feature);
03333
03334 if (option_verbose >= 1)
03335 ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, app, app_args, exten);
03336 }
03337 ast_config_destroy(cfg);
03338
03339
03340 if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
03341 if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
03342 notify_metermaids(old_parking_ext, old_parking_con);
03343 if (option_debug)
03344 ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
03345 }
03346
03347 if (!(con = ast_context_find(parking_con)) && !(con = ast_context_create(NULL, parking_con, registrar))) {
03348 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
03349 return -1;
03350 }
03351 res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
03352 if (parkaddhints)
03353 park_add_hints(parking_con, parking_start, parking_stop);
03354 if (!res)
03355 notify_metermaids(ast_parking_ext(), parking_con);
03356 return res;
03357
03358 }
03359
03360 static char *app_bridge = "Bridge";
03361 static char *bridge_synopsis = "Bridge two channels";
03362 static char *bridge_descrip =
03363 "Usage: Bridge(channel[|options])\n"
03364 " Allows the ability to bridge two channels via the dialplan.\n"
03365 "The current channel is bridged to the specified 'channel'.\n"
03366 "The following options are supported:\n"
03367 " p - Play a courtesy tone to 'channel'.\n"
03368 "BRIDGERESULT dial plan variable will contain SUCCESS, FAILURE, LOOP, NONEXISTENT or INCOMPATIBLE.\n";
03369
03370 enum {
03371 BRIDGE_OPT_PLAYTONE = (1 << 0),
03372 };
03373
03374 AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
03375 AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE)
03376 END_OPTIONS );
03377
03378 static int bridge_exec(struct ast_channel *chan, void *data)
03379 {
03380 struct ast_module_user *u;
03381 struct ast_channel *current_dest_chan, *final_dest_chan;
03382 char *tmp_data = NULL;
03383 struct ast_flags opts = { 0, };
03384 struct ast_bridge_config bconfig = { { 0, }, };
03385
03386 AST_DECLARE_APP_ARGS(args,
03387 AST_APP_ARG(dest_chan);
03388 AST_APP_ARG(options);
03389 );
03390
03391 if (ast_strlen_zero(data)) {
03392 ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
03393 return -1;
03394 }
03395
03396 u = ast_module_user_add(chan);
03397
03398 tmp_data = ast_strdupa(data);
03399 AST_STANDARD_APP_ARGS(args, tmp_data);
03400 if (!ast_strlen_zero(args.options))
03401 ast_app_parse_options(bridge_exec_options, &opts, NULL, args.options);
03402
03403
03404 if (!strncmp(chan->name, args.dest_chan,
03405 strlen(chan->name) < strlen(args.dest_chan) ?
03406 strlen(chan->name) : strlen(args.dest_chan))) {
03407 ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
03408 manager_event(EVENT_FLAG_CALL, "BridgeExec",
03409 "Response: Failed\r\n"
03410 "Reason: Unable to bridge channel to itself\r\n"
03411 "Channel1: %s\r\n"
03412 "Channel2: %s\r\n",
03413 chan->name, args.dest_chan);
03414 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
03415 ast_module_user_remove(u);
03416 return 0;
03417 }
03418
03419
03420 if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan,
03421 strlen(args.dest_chan)))) {
03422 ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
03423 "cannot get its lock\n", args.dest_chan);
03424 manager_event(EVENT_FLAG_CALL, "BridgeExec",
03425 "Response: Failed\r\n"
03426 "Reason: Cannot grab end point\r\n"
03427 "Channel1: %s\r\n"
03428 "Channel2: %s\r\n", chan->name, args.dest_chan);
03429 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
03430 ast_module_user_remove(u);
03431 return 0;
03432 }
03433 ast_mutex_unlock(¤t_dest_chan->lock);
03434
03435
03436 if (current_dest_chan->_state != AST_STATE_UP)
03437 ast_answer(current_dest_chan);
03438
03439
03440 if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
03441 NULL, NULL, 0, "Bridge/%s", current_dest_chan->name))) {
03442 ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
03443 manager_event(EVENT_FLAG_CALL, "BridgeExec",
03444 "Response: Failed\r\n"
03445 "Reason: cannot create placeholder\r\n"
03446 "Channel1: %s\r\n"
03447 "Channel2: %s\r\n", chan->name, args.dest_chan);
03448 }
03449 do_bridge_masquerade(current_dest_chan, final_dest_chan);
03450
03451
03452
03453 if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
03454 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
03455 manager_event(EVENT_FLAG_CALL, "BridgeExec",
03456 "Response: Failed\r\n"
03457 "Reason: Could not make channels compatible for bridge\r\n"
03458 "Channel1: %s\r\n"
03459 "Channel2: %s\r\n", chan->name, final_dest_chan->name);
03460 ast_hangup(final_dest_chan);
03461 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
03462 ast_module_user_remove(u);
03463 return 0;
03464 }
03465
03466
03467 manager_event(EVENT_FLAG_CALL, "BridgeExec",
03468 "Response: Success\r\n"
03469 "Channel1: %s\r\n"
03470 "Channel2: %s\r\n", chan->name, final_dest_chan->name);
03471
03472
03473 if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) {
03474 if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) {
03475 if (ast_waitstream(final_dest_chan, "") < 0)
03476 ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
03477 }
03478 }
03479
03480
03481 ast_bridge_call(chan, final_dest_chan, &bconfig);
03482
03483
03484 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
03485 if (!ast_check_hangup(final_dest_chan)) {
03486 if (option_debug) {
03487 ast_log(LOG_DEBUG, "starting new PBX in %s,%s,%d for chan %s\n",
03488 final_dest_chan->context, final_dest_chan->exten,
03489 final_dest_chan->priority, final_dest_chan->name);
03490 }
03491
03492 if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
03493 ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name);
03494 ast_hangup(final_dest_chan);
03495 } else if (option_debug)
03496 ast_log(LOG_DEBUG, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
03497 } else {
03498 if (option_debug)
03499 ast_log(LOG_DEBUG, "hangup chan %s since the other endpoint has hung up\n", final_dest_chan->name);
03500 ast_hangup(final_dest_chan);
03501 }
03502
03503 ast_module_user_remove(u);
03504
03505 return 0;
03506 }
03507
03508 static int reload(void)
03509 {
03510 autoanswer_reregister_extensions();
03511 return load_config();
03512 }
03513
03514 static int load_module(void)
03515 {
03516 int res;
03517
03518 ast_register_application(app_bridge, bridge_exec, bridge_synopsis, bridge_descrip);
03519
03520 memset(parking_ext, 0, sizeof(parking_ext));
03521 memset(parking_con, 0, sizeof(parking_con));
03522
03523 if ((res = load_config()))
03524 return res;
03525 ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
03526 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
03527 ast_pthread_create(&holding_thread, NULL, do_holding_thread, NULL);
03528 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
03529 if (!res)
03530 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
03531 if (!res) {
03532 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
03533 ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
03534 "Park a channel", mandescr_park);
03535 ast_manager_register2("Bridge", EVENT_FLAG_COMMAND, action_bridge, "Bridge two channels already in the PBX", mandescr_bridge);
03536 }
03537
03538 res |= ast_register_application(holdedcall, retrieve_call_exec, synopsis, descrip);
03539 ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
03540 if (!res)
03541 res |= ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
03542 if (!res)
03543 res |= ast_register_application(autoanswer, autoanswer_exec, synopsis4, descrip4);
03544
03545 res |= ast_devstate_prov_add("Park", metermaidstate);
03546
03547 return res;
03548 }
03549
03550
03551 static int unload_module(void)
03552 {
03553 ast_module_user_hangup_all();
03554
03555 ast_manager_unregister("ParkedCalls");
03556 ast_manager_unregister("Bridge");
03557 ast_manager_unregister("Park");
03558 ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
03559 ast_unregister_application(parkcall);
03560 ast_unregister_application(app_bridge);
03561 ast_unregister_application(autoanswer);
03562 ast_unregister_application(autoanswerlogin);
03563 ast_unregister_application(holdedcall);
03564 ast_devstate_prov_del("Park");
03565 return ast_unregister_application(parkedcall);
03566 }
03567
03568 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Call Features Resource",
03569 .load = load_module,
03570 .unload = unload_module,
03571 .reload = reload,
03572 );