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
01595
01596
01597 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
01598 switch (ntohs(aoh->option)) {
01599 case AST_OPTION_TONE_VERIFY:
01600 case AST_OPTION_TDD:
01601 case AST_OPTION_RELAXDTMF:
01602 case AST_OPTION_AUDIO_MODE:
01603 ast_channel_setoption(other, ntohs(aoh->option), aoh->data,
01604 f->datalen - sizeof(struct ast_option_header), 0);
01605 }
01606 }
01607 break;
01608 }
01609 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
01610
01611 } else if (f->frametype == AST_FRAME_DTMF) {
01612 char *featurecode;
01613 int sense;
01614
01615 hadfeatures = hasfeatures;
01616
01617 if (who == chan) {
01618 sense = FEATURE_SENSE_CHAN;
01619 featurecode = chan_featurecode;
01620 } else {
01621 sense = FEATURE_SENSE_PEER;
01622 featurecode = peer_featurecode;
01623 }
01624
01625
01626
01627
01628 featurecode[strlen(featurecode)] = f->subclass;
01629
01630 ast_frfree(f);
01631 f = NULL;
01632 config->feature_timer = backup_config.feature_timer;
01633 res = ast_feature_interpret(chan, peer, config, featurecode, sense);
01634 switch(res) {
01635 case FEATURE_RETURN_PASSDIGITS:
01636 ast_dtmf_stream(other, who, featurecode, 0);
01637
01638 case FEATURE_RETURN_SUCCESS:
01639 memset(featurecode, 0, sizeof(chan_featurecode));
01640 break;
01641 }
01642 if (res >= FEATURE_RETURN_PASSDIGITS) {
01643 res = 0;
01644 } else
01645 break;
01646 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
01647 if (hadfeatures && !hasfeatures) {
01648
01649 memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
01650 memset(&backup_config, 0, sizeof(struct ast_bridge_config));
01651 } else if (hasfeatures) {
01652 if (!hadfeatures) {
01653
01654 memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
01655
01656 config->play_warning = 0;
01657 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
01658 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
01659 config->warning_freq = 0;
01660 config->warning_sound = NULL;
01661 config->end_sound = NULL;
01662 config->start_sound = NULL;
01663 config->firstpass = 0;
01664 }
01665 config->start_time = ast_tvnow();
01666 config->feature_timer = featuredigittimeout;
01667 if (option_debug)
01668 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer);
01669 }
01670 }
01671 if (f)
01672 ast_frfree(f);
01673
01674 }
01675
01676
01677 bridge_cdr = ast_cdr_alloc();
01678 if (bridge_cdr) {
01679 if (chan->cdr && peer->cdr) {
01680 ast_channel_lock(chan);
01681 ast_cdr_init(bridge_cdr,chan);
01682 ast_cdr_start(bridge_cdr);
01683
01684
01685 ast_cdr_merge(bridge_cdr, chan->cdr);
01686 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
01687 ast_cdr_discard(chan->cdr);
01688
01689 chan->cdr = NULL;
01690
01691 ast_channel_unlock(chan);
01692
01693
01694 ast_channel_lock(peer);
01695 ast_cdr_merge(bridge_cdr, peer->cdr);
01696 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
01697 ast_cdr_discard(peer->cdr);
01698
01699 peer->cdr = NULL;
01700 ast_channel_unlock(peer);
01701
01702 ast_channel_lock(chan);
01703 chan->cdr = bridge_cdr;
01704 ast_channel_unlock(chan);
01705
01706 } else if (chan->cdr) {
01707
01708 ast_channel_lock(chan);
01709
01710 ast_cdr_init(bridge_cdr,chan);
01711
01712 ast_cdr_merge(bridge_cdr, chan->cdr);
01713 if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
01714 ast_cdr_discard(chan->cdr);
01715 chan->cdr = bridge_cdr;
01716 ast_channel_unlock(chan);
01717 } else if (peer->cdr) {
01718 ast_channel_lock(peer);
01719
01720 ast_cdr_init(bridge_cdr,peer);
01721
01722 ast_cdr_merge(bridge_cdr, peer->cdr);
01723 if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
01724 ast_cdr_discard(peer->cdr);
01725 peer->cdr = NULL;
01726 peer->cdr = bridge_cdr;
01727 ast_channel_unlock(peer);
01728 } else {
01729 ast_channel_lock(chan);
01730
01731 ast_cdr_init(bridge_cdr,chan);
01732 chan->cdr = bridge_cdr;
01733 ast_channel_unlock(chan);
01734 }
01735 if (ast_strlen_zero(bridge_cdr->dstchannel)) {
01736 if (strcmp(bridge_cdr->channel, peer->name) != 0)
01737 ast_cdr_setdestchan(bridge_cdr, peer->name);
01738 else
01739 ast_cdr_setdestchan(bridge_cdr, chan->name);
01740 }
01741 }
01742 return res;
01743 }
01744
01745 static void post_manager_event(const char *s, char *parkingexten, struct ast_channel *chan)
01746 {
01747 manager_event(EVENT_FLAG_CALL, s,
01748 "Exten: %s\r\n"
01749 "Channel: %s\r\n"
01750 "CallerID: %s\r\n"
01751 "CallerIDName: %s\r\n"
01752 "Uniqueid: %s\r\n\r\n",
01753 parkingexten,
01754 chan->name,
01755 S_OR(chan->cid.cid_num, "<unknown>"),
01756 S_OR(chan->cid.cid_name, "<unknown>"),
01757 chan->uniqueid
01758 );
01759 }
01760
01761
01762 static void *do_parking_thread(void *ignore)
01763 {
01764 fd_set rfds, efds;
01765 FD_ZERO(&rfds);
01766 FD_ZERO(&efds);
01767
01768 for (;;) {
01769 struct parkeduser *pu, *pl, *pt = NULL;
01770 int ms = -1;
01771 int max = -1;
01772 fd_set nrfds, nefds;
01773 FD_ZERO(&nrfds);
01774 FD_ZERO(&nefds);
01775
01776 ast_mutex_lock(&parking_lock);
01777 pl = NULL;
01778 pu = parkinglot;
01779
01780 while (pu) {
01781 struct ast_channel *chan = pu->chan;
01782 int tms;
01783 int x;
01784 struct ast_context *con;
01785
01786 if (pu->notquiteyet) {
01787 pl = pu;
01788 pu = pu->next;
01789 continue;
01790 }
01791 tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
01792 if (tms > pu->parkingtime) {
01793 ast_indicate(chan, AST_CONTROL_UNHOLD);
01794
01795 if (pu->peername[0]) {
01796 char *peername = ast_strdupa(pu->peername);
01797 char *cp = strrchr(peername, '-');
01798 if (cp)
01799 *cp = 0;
01800 con = ast_context_find(parking_con_dial);
01801 if (!con) {
01802 con = ast_context_create(NULL, parking_con_dial, registrar);
01803 if (!con)
01804 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
01805 }
01806 if (con) {
01807 char returnexten[AST_MAX_EXTENSION];
01808 snprintf(returnexten, sizeof(returnexten), "%s|30|t", peername);
01809 ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free, registrar);
01810 }
01811 set_c_e_p(chan, parking_con_dial, peername, 1);
01812 } else {
01813
01814
01815 set_c_e_p(chan, pu->context, pu->exten, pu->priority);
01816 }
01817
01818 post_manager_event("ParkedCallTimeOut", pu->parkingexten, chan);
01819
01820 if (option_verbose > 1)
01821 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);
01822
01823 if (ast_pbx_start(chan)) {
01824 ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
01825 ast_hangup(chan);
01826 }
01827
01828 if (pl)
01829 pl->next = pu->next;
01830 else
01831 parkinglot = pu->next;
01832 pt = pu;
01833 pu = pu->next;
01834 con = ast_context_find(parking_con);
01835 if (con) {
01836 if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
01837 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
01838 else
01839 notify_metermaids(pt->parkingexten, parking_con);
01840 } else
01841 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
01842 free(pt);
01843 } else {
01844 for (x = 0; x < AST_MAX_FDS; x++) {
01845 struct ast_frame *f;
01846
01847 if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
01848 continue;
01849
01850 if (FD_ISSET(chan->fds[x], &efds))
01851 ast_set_flag(chan, AST_FLAG_EXCEPTION);
01852 else
01853 ast_clear_flag(chan, AST_FLAG_EXCEPTION);
01854 chan->fdno = x;
01855
01856
01857 f = ast_read(chan);
01858 if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
01859 if (f)
01860 ast_frfree(f);
01861 post_manager_event("ParkedCallGiveUp", pu->parkingexten, chan);
01862
01863
01864 if (option_verbose > 1)
01865 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being parked\n", chan->name);
01866 ast_hangup(chan);
01867
01868 if (pl)
01869 pl->next = pu->next;
01870 else
01871 parkinglot = pu->next;
01872 pt = pu;
01873 pu = pu->next;
01874 con = ast_context_find(parking_con);
01875 if (con) {
01876 if (ast_context_remove_extension2(con, pt->parkingexten, 1, NULL))
01877 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
01878 else
01879 notify_metermaids(pt->parkingexten, parking_con);
01880 } else
01881 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
01882 free(pt);
01883 break;
01884 } else {
01885
01886 ast_frfree(f);
01887 if (pu->moh_trys < 3 && !chan->generatordata) {
01888 if (option_debug)
01889 ast_log(LOG_DEBUG, "MOH on parked call stopped by outside source. Restarting.\n");
01890 ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
01891 S_OR(parkmohclass, NULL),
01892 !ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
01893 pu->moh_trys++;
01894 }
01895 goto std;
01896 }
01897
01898 }
01899 if (x >= AST_MAX_FDS) {
01900 std: for (x=0; x<AST_MAX_FDS; x++) {
01901 if (chan->fds[x] > -1) {
01902 FD_SET(chan->fds[x], &nrfds);
01903 FD_SET(chan->fds[x], &nefds);
01904 if (chan->fds[x] > max)
01905 max = chan->fds[x];
01906 }
01907 }
01908
01909 if (tms < ms || ms < 0)
01910 ms = tms;
01911 pl = pu;
01912 pu = pu->next;
01913 }
01914 }
01915 }
01916 ast_mutex_unlock(&parking_lock);
01917 rfds = nrfds;
01918 efds = nefds;
01919 {
01920 struct timeval tv = ast_samp2tv(ms, 1000);
01921
01922 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
01923 }
01924 pthread_testcancel();
01925 }
01926 return NULL;
01927 }
01928
01929
01930 static int park_call_exec(struct ast_channel *chan, void *data)
01931 {
01932
01933
01934
01935 char *orig_chan_name = ast_strdupa(chan->name);
01936 char orig_exten[AST_MAX_EXTENSION];
01937 int orig_priority = chan->priority;
01938
01939
01940
01941 int res = 0;
01942 struct ast_module_user *u;
01943
01944 u = ast_module_user_add(chan);
01945
01946 ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
01947
01948
01949
01950 strcpy(chan->exten, "s");
01951 chan->priority = 1;
01952
01953 if (chan->_state != AST_STATE_UP)
01954 res = ast_answer(chan);
01955
01956 if (!res)
01957 res = ast_safe_sleep(chan, 1000);
01958
01959 if (!res) {
01960 res = park_call_full(chan, chan, 0, NULL, orig_chan_name);
01961
01962 if (res == 1) {
01963 ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
01964 chan->priority = orig_priority;
01965 res = 0;
01966 } else if (!res)
01967 res = AST_PBX_KEEPALIVE;
01968 }
01969
01970 ast_module_user_remove(u);
01971
01972 return res;
01973 }
01974
01975
01976 static int park_exec(struct ast_channel *chan, void *data)
01977 {
01978 int res = 0;
01979 struct ast_module_user *u;
01980 struct ast_channel *peer=NULL;
01981 struct parkeduser *pu, *pl=NULL;
01982 struct ast_context *con;
01983
01984 int park;
01985 struct ast_bridge_config config;
01986
01987 if (!data) {
01988 ast_log(LOG_WARNING, "Parkedcall requires an argument (extension number)\n");
01989 return -1;
01990 }
01991
01992 u = ast_module_user_add(chan);
01993
01994 park = atoi((char *)data);
01995 ast_mutex_lock(&parking_lock);
01996 pu = parkinglot;
01997 while(pu) {
01998 if (pu->parkingnum == park) {
01999 if (pl)
02000 pl->next = pu->next;
02001 else
02002 parkinglot = pu->next;
02003 break;
02004 }
02005 pl = pu;
02006 pu = pu->next;
02007 }
02008 ast_mutex_unlock(&parking_lock);
02009 if (pu) {
02010 peer = pu->chan;
02011 con = ast_context_find(parking_con);
02012 if (con) {
02013 if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
02014 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
02015 else
02016 notify_metermaids(pu->parkingexten, parking_con);
02017 } else
02018 ast_log(LOG_WARNING, "Whoa, no parking context?\n");
02019
02020 manager_event(EVENT_FLAG_CALL, "UnParkedCall",
02021 "Exten: %s\r\n"
02022 "Channel: %s\r\n"
02023 "From: %s\r\n"
02024 "CallerID: %s\r\n"
02025 "CallerIDName: %s\r\n"
02026 "Uniqueid: %s\r\n",
02027 pu->parkingexten, pu->chan->name, chan->name,
02028 S_OR(pu->chan->cid.cid_num, "<unknown>"),
02029 S_OR(pu->chan->cid.cid_name, "<unknown>"),
02030 pu->chan->uniqueid
02031 );
02032
02033 free(pu);
02034 }
02035
02036 if (chan->_state != AST_STATE_UP)
02037 ast_answer(chan);
02038
02039 if (peer) {
02040
02041
02042 if (!ast_strlen_zero(courtesytone)) {
02043 int error = 0;
02044 ast_indicate(peer, AST_CONTROL_UNHOLD);
02045 if (parkedplay == 0) {
02046 error = ast_stream_and_wait(chan, courtesytone, chan->language, "");
02047 } else if (parkedplay == 1) {
02048 error = ast_stream_and_wait(peer, courtesytone, chan->language, "");
02049 } else if (parkedplay == 2) {
02050 if (!ast_streamfile(chan, courtesytone, chan->language) &&
02051 !ast_streamfile(peer, courtesytone, chan->language)) {
02052
02053 res = ast_waitstream(chan, "");
02054 if (res >= 0)
02055 res = ast_waitstream(peer, "");
02056 if (res < 0)
02057 error = 1;
02058 }
02059 }
02060 if (error) {
02061 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
02062 ast_hangup(peer);
02063 ast_module_user_remove(u);
02064 return -1;
02065 }
02066 } else
02067 ast_indicate(peer, AST_CONTROL_UNHOLD);
02068
02069 res = ast_channel_make_compatible(chan, peer);
02070 if (res < 0) {
02071 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
02072 ast_hangup(peer);
02073 ast_module_user_remove(u);
02074 return -1;
02075 }
02076
02077
02078 if (option_verbose > 2)
02079 ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to parked call %d\n", chan->name, park);
02080
02081 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
02082 ast_cdr_setdestchan(chan->cdr, peer->name);
02083 memset(&config, 0, sizeof(struct ast_bridge_config));
02084 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
02085 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
02086 res = ast_bridge_call(chan, peer, &config);
02087
02088 pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
02089 ast_cdr_setdestchan(chan->cdr, peer->name);
02090
02091
02092 if (res != AST_PBX_NO_HANGUP_PEER)
02093 ast_hangup(peer);
02094 ast_module_user_remove(u);
02095 return res;
02096 } else {
02097
02098 if (ast_stream_and_wait(chan, "pbx-invalidpark", chan->language, ""))
02099 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
02100 if (option_verbose > 2)
02101 ast_verbose(VERBOSE_PREFIX_3 "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
02102 res = -1;
02103 }
02104
02105 ast_module_user_remove(u);
02106
02107 return res;
02108 }
02109
02110 int ast_hold_call(struct ast_channel *chan, struct ast_channel *peer)
02111 {
02112
02113
02114 struct holdeduser *pu;
02115 pu = malloc(sizeof(struct holdeduser));
02116 if (pu) {
02117 memset(pu, 0, sizeof(pu));
02118 ast_mutex_lock(&holding_lock);
02119 chan->appl = "Holded Call";
02120 chan->data = NULL;
02121
02122 pu->chan = chan;
02123 strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid));
02124 strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer));
02125
02126 ast_moh_start(pu->chan, NULL, NULL);
02127 gettimeofday(&pu->start, NULL);
02128 pu->next = holdlist;
02129 holdlist = pu;
02130 ast_mutex_unlock(&holding_lock);
02131
02132 pthread_kill(holding_thread, SIGURG);
02133
02134 manager_event(EVENT_FLAG_CALL, "HoldedCall",
02135 "Channel1: %s\r\n"
02136 "Channel2: %s\r\n"
02137 "Uniqueid1: %s\r\n"
02138 "Uniqueid2: %s\r\n"
02139 ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid);
02140
02141 } else {
02142 ast_log(LOG_WARNING, "Out of memory\n");
02143 return -1;
02144 }
02145 return 0;
02146 }
02147
02148 int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *peer)
02149 {
02150 struct ast_channel *chan;
02151 struct ast_frame *f;
02152
02153 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Onhold/%s",rchan->name);
02154 if (chan) {
02155
02156 ast_string_field_build(chan, name, "Onhold/%s",rchan->name);
02157
02158 chan->readformat = rchan->readformat;
02159 chan->writeformat = rchan->writeformat;
02160 ast_channel_masquerade(chan, rchan);
02161
02162 strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
02163 strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
02164 chan->priority = rchan->priority;
02165
02166 ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
02167
02168 f = ast_read(chan);
02169 if (f)
02170 ast_frfree(f);
02171 ast_hold_call(chan, peer);
02172 return -1;
02173 } else {
02174 ast_log(LOG_WARNING, "Unable to create holded channel\n");
02175 return -1;
02176 }
02177 return 0;
02178 }
02179
02180 int ast_retrieve_call(struct ast_channel *chan, char *uniqueid)
02181 {
02182 int res=-1, dres=-1;
02183 struct ast_channel *peer=NULL;
02184 struct ast_bridge_config config;
02185
02186 peer = ast_get_holded_call(uniqueid);
02187
02188
02189 if (chan->_state != AST_STATE_UP) {
02190 ast_answer(chan);
02191 }
02192
02193 if (peer) {
02194 ast_mutex_unlock(&peer->lock);
02195 ast_moh_stop(peer);
02196 res = ast_channel_make_compatible(chan, peer);
02197 if (res < 0) {
02198 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
02199 ast_hangup(peer);
02200 return -1;
02201 }
02202
02203
02204 if (option_verbose > 2)
02205 ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name);
02206
02207 memset(&config,0,sizeof(struct ast_bridge_config));
02208 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
02209 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
02210 config.timelimit = 0;
02211 config.play_warning = 0;
02212 config.warning_freq = 0;
02213 config.warning_sound=NULL;
02214 res = ast_bridge_call(chan,peer,&config);
02215
02216
02217 if (res != AST_PBX_NO_HANGUP_PEER)
02218 ast_hangup(peer);
02219 return res;
02220 } else {
02221
02222 dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
02223 if (!dres)
02224 dres = ast_waitstream(chan, "");
02225 else {
02226 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
02227 dres = 0;
02228 }
02229 }
02230 return res;
02231 }
02232
02233 int ast_retrieve_call_to_death(char *uniqueid)
02234 {
02235 int res=-1;
02236 struct ast_channel *peer=NULL;
02237
02238 peer = ast_get_holded_call(uniqueid);
02239
02240 if (peer) {
02241 res=0;
02242 if (option_verbose > 2)
02243 ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
02244 ast_mutex_unlock(&peer->lock);
02245 ast_hangup(peer);
02246 } else {
02247 ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid);
02248 }
02249 return res;
02250 }
02251
02252 struct ast_channel *ast_get_holded_call(char *uniqueid)
02253 {
02254 int res=-1;
02255 struct ast_channel *peer=NULL;
02256 struct holdeduser *pu, *pl=NULL;
02257
02258 ast_mutex_lock(&holding_lock);
02259 pu = holdlist;
02260 while(pu) {
02261 if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) {
02262 if (pl)
02263 pl->next = pu->next;
02264 else
02265 holdlist = pu->next;
02266 break;
02267 }
02268 pl = pu;
02269 pu = pu->next;
02270 }
02271 ast_mutex_unlock(&holding_lock);
02272 if (pu) {
02273 peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid);
02274 free(pu);
02275 if (peer) {
02276 res=0;
02277 if (option_verbose > 2)
02278 ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
02279 ast_moh_stop(peer);
02280 return peer;
02281 } else {
02282 if (option_verbose > 2)
02283 ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid);
02284 return NULL;
02285 }
02286 } else {
02287 ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid);
02288 }
02289 return NULL;
02290 }
02291
02292
02293 static void *do_holding_thread(void *ignore)
02294 {
02295 int ms, tms, max;
02296 struct holdeduser *pu, *pl, *pt = NULL;
02297 struct timeval tv;
02298 struct ast_frame *f;
02299 int x;
02300 fd_set rfds, efds;
02301 fd_set nrfds, nefds;
02302 FD_ZERO(&rfds);
02303 FD_ZERO(&efds);
02304 for (;;) {
02305 ms = -1;
02306 max = -1;
02307 ast_mutex_lock(&holding_lock);
02308 pl = NULL;
02309 pu = holdlist;
02310 gettimeofday(&tv, NULL);
02311 FD_ZERO(&nrfds);
02312 FD_ZERO(&nefds);
02313 while(pu) {
02314 tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
02315 for (x=0;x<AST_MAX_FDS;x++) {
02316 if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
02317 if (FD_ISSET(pu->chan->fds[x], &efds))
02318 ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
02319 else
02320 ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
02321 pu->chan->fdno = x;
02322
02323 f = ast_read(pu->chan);
02324 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
02325
02326 if (option_verbose > 1)
02327 ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being onhold\n", pu->chan->name);
02328 ast_hangup(pu->chan);
02329
02330
02331
02332 if (pl)
02333 pl->next = pu->next;
02334 else
02335 holdlist = pu->next;
02336 pt = pu;
02337 pu = pu->next;
02338 free(pt);
02339 break;
02340 } else {
02341
02342 ast_frfree(f);
02343 goto std;
02344 }
02345 }
02346 }
02347 if (x >= AST_MAX_FDS) {
02348 std: for (x=0;x<AST_MAX_FDS;x++) {
02349
02350 if (pu->chan->fds[x] > -1) {
02351 FD_SET(pu->chan->fds[x], &nrfds);
02352 FD_SET(pu->chan->fds[x], &nefds);
02353 if (pu->chan->fds[x] > max)
02354 max = pu->chan->fds[x];
02355 }
02356 }
02357
02358 if ((tms < ms) || (ms < 0))
02359 ms = tms;
02360 pl = pu;
02361 pu = pu->next;
02362 }
02363 }
02364 ast_mutex_unlock(&holding_lock);
02365 rfds = nrfds;
02366 efds = nefds;
02367 tv.tv_sec = ms / 1000;
02368 tv.tv_usec = (ms % 1000) * 1000;
02369
02370 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
02371 pthread_testcancel();
02372 }
02373 return NULL;
02374 }
02375
02376 static int retrieve_call_exec(struct ast_channel *chan, void *data) {
02377 int res=0;
02378 struct ast_module_user *u;
02379 char *uniqueid = (char *)data;
02380 u = ast_module_user_add(chan);
02381 res = ast_retrieve_call(chan, uniqueid);
02382 ast_module_user_remove(u);
02383 return res;
02384 }
02385
02386 static int handle_showfeatures(int fd, int argc, char *argv[])
02387 {
02388 int i;
02389 struct ast_call_feature *feature;
02390 char format[] = "%-25s %-7s %-7s\n";
02391
02392 ast_cli(fd, format, "Builtin Feature", "Default", "Current");
02393 ast_cli(fd, format, "---------------", "-------", "-------");
02394
02395 ast_cli(fd, format, "Pickup", "*8", ast_pickup_ext());
02396
02397 ast_rwlock_rdlock(&features_lock);
02398 for (i = 0; i < FEATURES_COUNT; i++)
02399 ast_cli(fd, format, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
02400 ast_rwlock_unlock(&features_lock);
02401
02402 ast_cli(fd, "\n");
02403 ast_cli(fd, format, "Dynamic Feature", "Default", "Current");
02404 ast_cli(fd, format, "---------------", "-------", "-------");
02405 if (AST_LIST_EMPTY(&feature_list))
02406 ast_cli(fd, "(none)\n");
02407 else {
02408 AST_LIST_LOCK(&feature_list);
02409 AST_LIST_TRAVERSE(&feature_list, feature, feature_entry)
02410 ast_cli(fd, format, feature->sname, "no def", feature->exten);
02411 AST_LIST_UNLOCK(&feature_list);
02412 }
02413 ast_cli(fd, "\nCall parking\n");
02414 ast_cli(fd, "------------\n");
02415 ast_cli(fd,"%-20s: %s\n", "Parking extension", parking_ext);
02416 ast_cli(fd,"%-20s: %s\n", "Parking context", parking_con);
02417 ast_cli(fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
02418 ast_cli(fd,"\n");
02419
02420 return RESULT_SUCCESS;
02421 }
02422
02423 static char mandescr_bridge[] =
02424 "Description: Bridge together two channels already in the PBX\n"
02425 "Variables: ( Headers marked with * are required )\n"
02426 " *Channel1: Channel to Bridge to Channel2\n"
02427 " *Channel2: Channel to Bridge to Channel1\n"
02428 " Tone: (Yes|No) Play courtesy tone to Channel 2\n"
02429 "\n";
02430
02431 static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
02432 {
02433 ast_moh_stop(chan);
02434 ast_mutex_lock(&chan->lock);
02435 ast_setstate(tmpchan, chan->_state);
02436 tmpchan->readformat = chan->readformat;
02437 tmpchan->writeformat = chan->writeformat;
02438 ast_channel_masquerade(tmpchan, chan);
02439 ast_mutex_lock(&tmpchan->lock);
02440 ast_do_masquerade(tmpchan);
02441
02442 ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
02443 ast_mutex_unlock(&tmpchan->lock);
02444 ast_mutex_unlock(&chan->lock);
02445 }
02446
02447 static int action_bridge(struct mansession *s, const struct message *m)
02448 {
02449 const char *channela = astman_get_header(m, "Channel1");
02450 const char *channelb = astman_get_header(m, "Channel2");
02451 const char *playtone = astman_get_header(m, "Tone");
02452 struct ast_channel *chana = NULL, *chanb = NULL;
02453 struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
02454 struct ast_bridge_thread_obj *tobj = NULL;
02455
02456
02457 if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) {
02458 chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
02459 chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
02460 if (chana)
02461 ast_mutex_unlock(&chana->lock);
02462 if (chanb)
02463 ast_mutex_unlock(&chanb->lock);
02464
02465
02466 if (!chana) {
02467 char buf[256];
02468 snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
02469 astman_send_error(s, m, buf);
02470 return 0;
02471 }
02472 if (!chanb) {
02473 char buf[256];
02474 snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
02475 astman_send_error(s, m, buf);
02476 return 0;
02477 }
02478 } else {
02479 astman_send_error(s, m, "Missing channel parameter in request");
02480 return 0;
02481 }
02482
02483
02484 if (chana->_state != AST_STATE_UP)
02485 ast_answer(chana);
02486 if (chanb->_state != AST_STATE_UP)
02487 ast_answer(chanb);
02488
02489
02490 if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
02491 NULL, NULL, 0, "Bridge/%s", chana->name))) {
02492 astman_send_error(s, m, "Unable to create temporary channel!");
02493 return 1;
02494 }
02495
02496 if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
02497 NULL, NULL, 0, "Bridge/%s", chanb->name))) {
02498 astman_send_error(s, m, "Unable to create temporary channels!");
02499 ast_channel_free(tmpchana);
02500 return 1;
02501 }
02502
02503 do_bridge_masquerade(chana, tmpchana);
02504 do_bridge_masquerade(chanb, tmpchanb);
02505
02506
02507 if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
02508 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
02509 astman_send_error(s, m, "Could not make channels compatible for manager bridge");
02510 ast_hangup(tmpchana);
02511 ast_hangup(tmpchanb);
02512 return 1;
02513 }
02514
02515
02516 if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
02517 ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
02518 astman_send_error(s, m, "Unable to spawn a new bridge thread");
02519 ast_hangup(tmpchana);
02520 ast_hangup(tmpchanb);
02521 return 1;
02522 }
02523
02524 tobj->chan = tmpchana;
02525 tobj->peer = tmpchanb;
02526 tobj->return_to_pbx = 1;
02527
02528 if (ast_true(playtone)) {
02529 if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
02530 if (ast_waitstream(tmpchanb, "") < 0)
02531 ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
02532 }
02533 }
02534
02535 ast_bridge_call_thread_launch(tobj);
02536
02537 astman_send_ack(s, m, "Launched bridge thread with success");
02538
02539 return 0;
02540 }
02541
02542 static char showfeatures_help[] =
02543 "Usage: feature list\n"
02544 " Lists currently configured features.\n";
02545
02546 static int handle_parkedcalls(int fd, int argc, char *argv[])
02547 {
02548 struct parkeduser *cur;
02549 int numparked = 0;
02550
02551 ast_cli(fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
02552 , "Context", "Extension", "Pri", "Timeout");
02553
02554 ast_mutex_lock(&parking_lock);
02555
02556 for (cur = parkinglot; cur; cur = cur->next) {
02557 ast_cli(fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
02558 ,cur->parkingexten, cur->chan->name, cur->context, cur->exten
02559 ,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
02560
02561 numparked++;
02562 }
02563 ast_mutex_unlock(&parking_lock);
02564 ast_cli(fd, "%d parked call%s.\n", numparked, (numparked != 1) ? "s" : "");
02565
02566
02567 return RESULT_SUCCESS;
02568 }
02569
02570 static char showparked_help[] =
02571 "Usage: show parkedcalls\n"
02572 " Lists currently parked calls.\n";
02573
02574 static struct ast_cli_entry cli_show_features_deprecated = {
02575 { "show", "features", NULL },
02576 handle_showfeatures, NULL,
02577 NULL };
02578
02579 static char showautoanswer_help[] =
02580 "Usage: show autoanswer\n"
02581 " Lists currently logged in autoanswer users.\n";
02582
02583
02584
02585 static int manager_parking_status( struct mansession *s, const struct message *m)
02586 {
02587 struct parkeduser *cur;
02588 const char *id = astman_get_header(m, "ActionID");
02589 char idText[256] = "";
02590
02591 if (!ast_strlen_zero(id))
02592 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
02593
02594 astman_send_ack(s, m, "Parked calls will follow");
02595
02596 ast_mutex_lock(&parking_lock);
02597
02598 for (cur = parkinglot; cur; cur = cur->next) {
02599 astman_append(s, "Event: ParkedCall\r\n"
02600 "Exten: %d\r\n"
02601 "Channel: %s\r\n"
02602 "From: %s\r\n"
02603 "Timeout: %ld\r\n"
02604 "CallerID: %s\r\n"
02605 "CallerIDName: %s\r\n"
02606 "Uniqueid: %s\r\n\r\n"
02607 "%s"
02608 "\r\n",
02609 cur->parkingnum, cur->chan->name, cur->peername,
02610 (long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
02611 S_OR(cur->chan->cid.cid_num, ""),
02612 S_OR(cur->chan->cid.cid_name, ""), cur->chan->uniqueid,
02613 idText);
02614 }
02615
02616 astman_append(s,
02617 "Event: ParkedCallsComplete\r\n"
02618 "%s"
02619 "\r\n",idText);
02620
02621 ast_mutex_unlock(&parking_lock);
02622
02623 return RESULT_SUCCESS;
02624 }
02625
02626 static char mandescr_park[] =
02627 "Description: Park a channel.\n"
02628 "Variables: (Names marked with * are required)\n"
02629 " *Channel: Channel name to park\n"
02630 " *Channel2: Channel to announce park info to (and return to if timeout)\n"
02631 " Timeout: Number of milliseconds to wait before callback.\n";
02632
02633 static int manager_park(struct mansession *s, const struct message *m)
02634 {
02635 const char *channel = astman_get_header(m, "Channel");
02636 const char *channel2 = astman_get_header(m, "Channel2");
02637 const char *timeout = astman_get_header(m, "Timeout");
02638 char buf[BUFSIZ];
02639 int to = 0;
02640 int res = 0;
02641 int parkExt = 0;
02642 struct ast_channel *ch1, *ch2;
02643
02644 if (ast_strlen_zero(channel)) {
02645 astman_send_error(s, m, "Channel not specified");
02646 return 0;
02647 }
02648
02649 if (ast_strlen_zero(channel2)) {
02650 astman_send_error(s, m, "Channel2 not specified");
02651 return 0;
02652 }
02653
02654 ch1 = ast_get_channel_by_name_locked(channel);
02655 if (!ch1) {
02656 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
02657 astman_send_error(s, m, buf);
02658 return 0;
02659 }
02660
02661 ch2 = ast_get_channel_by_name_locked(channel2);
02662 if (!ch2) {
02663 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
02664 astman_send_error(s, m, buf);
02665 ast_channel_unlock(ch1);
02666 return 0;
02667 }
02668
02669 if (!ast_strlen_zero(timeout)) {
02670 sscanf(timeout, "%d", &to);
02671 }
02672
02673 res = ast_masq_park_call(ch1, ch2, to, &parkExt);
02674 if (!res) {
02675 ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
02676 astman_send_ack(s, m, "Park successful");
02677 } else {
02678 astman_send_error(s, m, "Park failure");
02679 }
02680
02681 ast_channel_unlock(ch1);
02682 ast_channel_unlock(ch2);
02683
02684 return 0;
02685 }
02686
02687 static int handle_autoanswer(int fd, int argc, char *argv[])
02688 {
02689 struct aauser *cur;
02690
02691 ast_cli(fd, "%25s %10s %15s \n", "Channel"
02692 , "Extension", "Context");
02693
02694 ast_mutex_lock(&autoanswer_lock);
02695
02696 cur=aalot;
02697 while(cur) {
02698 ast_cli(fd, "%25s %10s %15s\n",cur->chan->name, cur->exten, cur->context);
02699
02700 cur = cur->next;
02701 }
02702
02703 ast_mutex_unlock(&autoanswer_lock);
02704
02705 return RESULT_SUCCESS;
02706 }
02707
02708 static struct ast_cli_entry cli_features[] = {
02709 { { "feature", "list", NULL },
02710 handle_showfeatures, "Lists configured features",
02711 showfeatures_help, NULL, &cli_show_features_deprecated },
02712
02713 { { "show", "parkedcalls", NULL },
02714 handle_parkedcalls, "Lists parked calls",
02715 showparked_help },
02716
02717 { { "show", "autoanswer", NULL },
02718 handle_autoanswer, "Lists autoanswer users",
02719 showautoanswer_help },
02720 };
02721 int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data)
02722 {
02723 struct ast_channel *chan;
02724 struct ast_frame *f;
02725
02726 chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Autoanswer/%s", rchan->name);
02727 if (chan) {
02728
02729 ast_string_field_build(chan, name, "Autoanswer/%s",rchan->name);
02730
02731 chan->readformat = rchan->readformat;
02732 chan->writeformat = rchan->writeformat;
02733 ast_channel_masquerade(chan, rchan);
02734
02735 strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
02736 strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
02737 chan->priority = rchan->priority;
02738
02739 ast_string_field_build(chan, uniqueid, "%s",rchan->uniqueid);
02740
02741 f = ast_read(chan);
02742 if (f)
02743 ast_frfree(f);
02744 ast_autoanswer_login(chan, data);
02745 } else {
02746 ast_log(LOG_WARNING, "Unable to create aa channel\n");
02747 return -1;
02748 }
02749 return 0;
02750 }
02751
02752 static int autoanswer_login_exec(struct ast_channel *chan, void *data)
02753 {
02754 int res=0;
02755 struct ast_module_user *u;
02756
02757 u = ast_module_user_add(chan);
02758 if (!data) {
02759 ast_log(LOG_WARNING, "AutoanswerLogin requires an argument (extension number)\n");
02760 return -1;
02761 }
02762 res = ast_masq_autoanswer_login(chan, data);
02763 ast_module_user_remove(u);
02764 return res;
02765 }
02766
02767 int ast_autoanswer_login(struct ast_channel *chan, void *data)
02768 {
02769
02770
02771 struct ast_context *con;
02772 char exten[AST_MAX_EXTENSION];
02773 struct aauser *pu,*pl = NULL;
02774 char *s, *stringp, *aacontext, *aaexten = NULL;
02775
02776 s = ast_strdupa((void *) data);
02777 stringp=s;
02778 aacontext = strsep(&stringp, "|");
02779 aaexten = strsep(&stringp, "|");
02780 if (!aaexten) {
02781 aaexten = aacontext;
02782 aacontext = NULL;
02783 }
02784 if (!aaexten) {
02785 ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
02786 return -1;
02787 } else {
02788 if (!aacontext) {
02789 aacontext = "default";
02790 }
02791 }
02792
02793 ast_mutex_lock(&autoanswer_lock);
02794 pu = aalot;
02795 while(pu) {
02796 if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
02797 if (pl)
02798 pl->next = pu->next;
02799 else
02800 aalot = pu->next;
02801 break;
02802 }
02803 pl = pu;
02804 pu = pu->next;
02805 }
02806 ast_mutex_unlock(&autoanswer_lock);
02807 if (pu) {
02808 ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context);
02809 manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
02810 "Channel: %s\r\n"
02811 "Uniqueid: %s\r\n"
02812 "Context: %s\r\n"
02813 "Exten: %s\r\n"
02814 ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
02815 ast_hangup(pu->chan);
02816 free(pu);
02817 }
02818 pu = malloc(sizeof(struct aauser));
02819 if (pu) {
02820 memset(pu, 0, sizeof(pu));
02821 ast_mutex_lock(&autoanswer_lock);
02822 chan->appl = "Autoanswer";
02823 chan->data = NULL;
02824
02825 pu->chan = chan;
02826 if (chan->_state != AST_STATE_UP) {
02827 ast_answer(chan);
02828 }
02829
02830
02831 ast_moh_start(pu->chan, NULL, NULL);
02832 gettimeofday(&pu->start, NULL);
02833 strncpy(pu->exten, aaexten, sizeof(pu->exten)-1);
02834 strncpy(pu->context, aacontext, sizeof(pu->exten)-1);
02835 pu->next = aalot;
02836 aalot = pu;
02837 con = ast_context_find(aacontext);
02838 if (!con) {
02839 con = ast_context_create(NULL,aacontext, registrar);
02840 if (!con) {
02841 ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext);
02842 }
02843 }
02844 if (con) {
02845 snprintf(exten, sizeof(exten), "%s", aaexten);
02846 ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar);
02847 }
02848
02849 ast_mutex_unlock(&autoanswer_lock);
02850
02851 pthread_kill(autoanswer_thread, SIGURG);
02852 if (option_verbose > 1)
02853 ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context);
02854 manager_event(EVENT_FLAG_CALL, "AutoanswerLogin",
02855 "Channel: %s\r\n"
02856 "Uniqueid: %s\r\n"
02857 "Context: %s\r\n"
02858 "Exten: %s\r\n"
02859 ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
02860
02861 return 0;
02862 } else {
02863 ast_log(LOG_WARNING, "Out of memory\n");
02864 return -1;
02865 }
02866 return 0;
02867 }
02868
02869 static void autoanswer_reregister_extensions(void)
02870 {
02871 struct aauser *cur;
02872 struct ast_context *con;
02873 char exten[AST_MAX_EXTENSION];
02874 char args[AST_MAX_EXTENSION];
02875
02876 ast_mutex_lock(&autoanswer_lock);
02877
02878 cur=aalot;
02879 while(cur) {
02880 con = ast_context_find(cur->context);
02881 if (!con) {
02882 con = ast_context_create(NULL,cur->context, registrar);
02883 if (!con) {
02884 ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", cur->context);
02885 }
02886 }
02887 if (con) {
02888 snprintf(exten, sizeof(exten), "%s", cur->exten);
02889 snprintf(args, sizeof(args), "%s|%s", cur->context, cur->exten);
02890 ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)args), free, registrar);
02891 }
02892 cur = cur->next;
02893 }
02894
02895 ast_mutex_unlock(&autoanswer_lock);
02896 }
02897 static void *do_autoanswer_thread(void *ignore)
02898 {
02899 int ms, tms, max;
02900 struct ast_context *con;
02901 char exten[AST_MAX_EXTENSION];
02902 struct aauser *pu, *pl, *pt = NULL;
02903 struct timeval tv;
02904 struct ast_frame *f;
02905 int x;
02906 fd_set rfds, efds;
02907 fd_set nrfds, nefds;
02908 FD_ZERO(&rfds);
02909 FD_ZERO(&efds);
02910 for (;;) {
02911 ms = -1;
02912 max = -1;
02913 ast_mutex_lock(&autoanswer_lock);
02914 pl = NULL;
02915 pu = aalot;
02916 gettimeofday(&tv, NULL);
02917 FD_ZERO(&nrfds);
02918 FD_ZERO(&nefds);
02919 while(pu) {
02920 tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
02921 for (x=0;x<AST_MAX_FDS;x++) {
02922 if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
02923 if (FD_ISSET(pu->chan->fds[x], &efds))
02924 ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
02925 else
02926 ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
02927 pu->chan->fdno = x;
02928
02929 f = ast_read(pu->chan);
02930 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
02931
02932 if (option_verbose > 1)
02933 ast_verbose(VERBOSE_PREFIX_2 "%s logged out of autoanswer app\n", pu->chan->name);
02934 manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
02935 "Channel: %s\r\n"
02936 "Uniqueid: %s\r\n"
02937 "Context: %s\r\n"
02938 "Exten: %s\r\n"
02939 ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
02940 ast_hangup(pu->chan);
02941 con = ast_context_find(pu->context);
02942 if (con) {
02943 snprintf(exten, sizeof(exten), "%s", pu->exten);
02944 if (ast_context_remove_extension2(con, exten, 1, registrar))
02945 ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
02946 } else {
02947 ast_log(LOG_WARNING, "Whoa, no %s context?\n", pu->exten);
02948 }
02949
02950 if (pl)
02951 pl->next = pu->next;
02952 else
02953 aalot = pu->next;
02954 pt = pu;
02955 pu = pu->next;
02956 free(pt);
02957 break;
02958 } else {
02959
02960 ast_frfree(f);
02961 goto std;
02962 }
02963 }
02964 }
02965 if (x >= AST_MAX_FDS) {
02966 std: for (x=0;x<AST_MAX_FDS;x++) {
02967
02968 if (pu->chan->fds[x] > -1) {
02969 FD_SET(pu->chan->fds[x], &nrfds);
02970 FD_SET(pu->chan->fds[x], &nefds);
02971 if (pu->chan->fds[x] > max)
02972 max = pu->chan->fds[x];
02973 }
02974 }
02975
02976 if ((tms < ms) || (ms < 0))
02977 ms = tms;
02978 pl = pu;
02979 pu = pu->next;
02980 }
02981 }
02982 ast_mutex_unlock(&autoanswer_lock);
02983 rfds = nrfds;
02984 efds = nefds;
02985 tv.tv_sec = ms / 1000;
02986 tv.tv_usec = (ms % 1000) * 1000;
02987
02988 ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
02989 pthread_testcancel();
02990 }
02991 return NULL;
02992 }
02993
02994 static int autoanswer_exec(struct ast_channel *chan, void *data)
02995 {
02996 int res=0;
02997 struct ast_channel *peer=NULL;
02998 struct aauser *pu, *pl=NULL;
02999 struct ast_bridge_config config;
03000 char *s, *stringp, *aacontext, *aaexten = NULL;
03001 char datastring[80];
03002 struct ast_module_user *u;
03003
03004
03005 if (!data) {
03006 ast_log(LOG_WARNING, "Autoanswer requires an argument (extension number)\n");
03007 return -1;
03008 }
03009 s = ast_strdupa((void *) data);
03010 stringp=s;
03011 aacontext = strsep(&stringp, "|");
03012 aaexten = strsep(&stringp, "|");
03013 if (!aaexten) {
03014 aaexten = aacontext;
03015 aacontext = NULL;
03016 }
03017 if (!aaexten) {
03018 ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
03019 return -1;
03020 } else {
03021 if (!aacontext) {
03022 aacontext = "default";
03023 }
03024 }
03025
03026 u = ast_module_user_add(chan);
03027 ast_mutex_lock(&autoanswer_lock);
03028 pu = aalot;
03029 while(pu) {
03030 if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
03031 if (pl)
03032 pl->next = pu->next;
03033 else
03034 aalot = pu->next;
03035 break;
03036 }
03037 pl = pu;
03038 pu = pu->next;
03039 }
03040 ast_mutex_unlock(&autoanswer_lock);
03041 if (pu) {
03042 peer = pu->chan;
03043 free(pu);
03044 pu = NULL;
03045 }
03046
03047 if (chan->_state != AST_STATE_UP) {
03048 ast_answer(chan);
03049 }
03050
03051 if (peer) {
03052 ast_moh_stop(peer);
03053
03054 if (!ast_strlen_zero(courtesytone)) {
03055 if (!ast_streamfile(peer, courtesytone, peer->language)) {
03056 if (ast_waitstream(peer, "") < 0) {
03057 ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
03058 ast_hangup(peer);
03059 return -1;
03060 }
03061 }
03062 }
03063
03064 res = ast_channel_make_compatible(chan, peer);
03065 if (res < 0) {
03066 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
03067 ast_hangup(peer);
03068 return -1;
03069 }
03070
03071
03072 if (option_verbose > 2)
03073 ast_verbose(VERBOSE_PREFIX_3 "Channel %s autoanswered %s\n", peer->name, chan->name);
03074 manager_event(EVENT_FLAG_CALL, "Autoanswer",
03075 "Channel: %s\r\n"
03076 "Uniqueid: %s\r\n"
03077 "Channel2: %s\r\n"
03078 "Uniqueid2: %s\r\n"
03079 "Context: %s\r\n"
03080 "Exten: %s\r\n"
03081 ,chan->name, chan->uniqueid, peer->name, peer->uniqueid, aacontext, aaexten);
03082
03083
03084 memset(&config,0,sizeof(struct ast_bridge_config));
03085 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
03086 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
03087 config.timelimit = 0;
03088 config.play_warning = 0;
03089 config.warning_freq = 0;
03090 config.warning_sound=NULL;
03091 res = ast_bridge_call(chan,peer,&config);
03092
03093 if (option_verbose > 2)
03094 ast_verbose(VERBOSE_PREFIX_3 "returning from bridge %s\n", peer->name);
03095
03096 snprintf(datastring, sizeof(datastring) - 1, "%s|%s", aacontext, aaexten);
03097 ast_autoanswer_login(peer, datastring);
03098 return res;
03099 } else {
03100 if (option_verbose > 2)
03101 ast_verbose(VERBOSE_PREFIX_3 "Nobody logged in for autoanswer %s@%s\n", aaexten, aacontext);
03102 res = -1;
03103 }
03104 ast_module_user_remove(u);
03105 return res;
03106 }
03107
03108
03109 int ast_pickup_call(struct ast_channel *chan)
03110 {
03111 struct ast_channel *cur = NULL;
03112 int res = -1;
03113
03114 while ( (cur = ast_channel_walk_locked(cur)) != NULL) {
03115 if (!cur->pbx &&
03116 (cur != chan) &&
03117 (chan->pickupgroup & cur->callgroup) &&
03118 ((cur->_state == AST_STATE_RINGING) ||
03119 (cur->_state == AST_STATE_RING))) {
03120 break;
03121 }
03122 ast_channel_unlock(cur);
03123 }
03124 if (cur) {
03125 if (option_debug)
03126 ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
03127 res = ast_answer(chan);
03128 if (res)
03129 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
03130 res = ast_queue_control(chan, AST_CONTROL_ANSWER);
03131 if (res)
03132 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
03133 res = ast_channel_masquerade(cur, chan);
03134 if (res)
03135 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name);
03136 ast_channel_unlock(cur);
03137 } else {
03138 if (option_debug)
03139 ast_log(LOG_DEBUG, "No call pickup possible...\n");
03140 }
03141 return res;
03142 }
03143
03144
03145 static void park_add_hints(char *context, int start, int stop)
03146 {
03147 int numext;
03148 char device[AST_MAX_EXTENSION];
03149 char exten[10];
03150
03151 for (numext = start; numext <= stop; numext++) {
03152 snprintf(exten, sizeof(exten), "%d", numext);
03153 snprintf(device, sizeof(device), "park:%s@%s", exten, context);
03154 ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
03155 }
03156 }
03157
03158
03159 static int load_config(void)
03160 {
03161 int start = 0, end = 0;
03162 int res;
03163 struct ast_context *con = NULL;
03164 struct ast_config *cfg = NULL;
03165 struct ast_variable *var = NULL;
03166 char old_parking_ext[AST_MAX_EXTENSION];
03167 char old_parking_con[AST_MAX_EXTENSION] = "";
03168
03169 if (!ast_strlen_zero(parking_con)) {
03170 strcpy(old_parking_ext, parking_ext);
03171 strcpy(old_parking_con, parking_con);
03172 }
03173
03174
03175 strcpy(parking_con, "parkedcalls");
03176 strcpy(parking_con_dial, "park-dial");
03177 strcpy(parking_ext, "700");
03178 strcpy(pickup_ext, "*8");
03179 strcpy(parkmohclass, "default");
03180 courtesytone[0] = '\0';
03181 strcpy(xfersound, "beep");
03182 strcpy(xferfailsound, "pbx-invalid");
03183 parking_start = 701;
03184 parking_stop = 750;
03185 parkfindnext = 0;
03186 adsipark = 0;
03187 parkaddhints = 0;
03188
03189 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
03190 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
03191 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
03192
03193 cfg = ast_config_load("features.conf");
03194 if (!cfg) {
03195 ast_log(LOG_WARNING,"Could not load features.conf\n");
03196 return AST_MODULE_LOAD_DECLINE;
03197 }
03198 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
03199 if (!strcasecmp(var->name, "parkext")) {
03200 ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
03201 } else if (!strcasecmp(var->name, "context")) {
03202 ast_copy_string(parking_con, var->value, sizeof(parking_con));
03203 } else if (!strcasecmp(var->name, "parkingtime")) {
03204 if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
03205 ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
03206 parkingtime = DEFAULT_PARK_TIME;
03207 } else
03208 parkingtime = parkingtime * 1000;
03209 } else if (!strcasecmp(var->name, "parkpos")) {
03210 if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
03211 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);
03212 } else {
03213 parking_start = start;
03214 parking_stop = end;
03215 }
03216 } else if (!strcasecmp(var->name, "findslot")) {
03217 parkfindnext = (!strcasecmp(var->value, "next"));
03218 } else if (!strcasecmp(var->name, "parkinghints")) {
03219 parkaddhints = ast_true(var->value);
03220 } else if (!strcasecmp(var->name, "adsipark")) {
03221 adsipark = ast_true(var->value);
03222 } else if (!strcasecmp(var->name, "transferdigittimeout")) {
03223 if ((sscanf(var->value, "%d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
03224 ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
03225 transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
03226 } else
03227 transferdigittimeout = transferdigittimeout * 1000;
03228 } else if (!strcasecmp(var->name, "featuredigittimeout")) {
03229 if ((sscanf(var->value, "%d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
03230 ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
03231 featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
03232 }
03233 } else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
03234 if ((sscanf(var->value, "%d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
03235 ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
03236 atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
03237 } else
03238 atxfernoanswertimeout = atxfernoanswertimeout * 1000;
03239 } else if (!strcasecmp(var->name, "courtesytone")) {
03240 ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
03241 } else if (!strcasecmp(var->name, "parkedplay")) {
03242 if (!strcasecmp(var->value, "both"))
03243 parkedplay = 2;
03244 else if (!strcasecmp(var->value, "parked"))
03245 parkedplay = 1;
03246 else
03247 parkedplay = 0;
03248 } else if (!strcasecmp(var->name, "xfersound")) {
03249 ast_copy_string(xfersound, var->value, sizeof(xfersound));
03250 } else if (!strcasecmp(var->name, "xferfailsound")) {
03251 ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
03252 } else if (!strcasecmp(var->name, "pickupexten")) {
03253 ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
03254 } else if (!strcasecmp(var->name, "parkedmusicclass")) {
03255 ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
03256 }
03257 }
03258
03259 unmap_features();
03260 for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
03261 if (remap_feature(var->name, var->value))
03262 ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
03263 }
03264
03265
03266 ast_unregister_features();
03267 for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
03268 char *tmp_val = ast_strdupa(var->value);
03269 char *exten, *activateon, *activatedby, *app, *app_args, *moh_class;
03270 struct ast_call_feature *feature;
03271
03272
03273
03274
03275
03276 exten = strsep(&tmp_val,",");
03277 activatedby = strsep(&tmp_val,",");
03278 app = strsep(&tmp_val,",");
03279 app_args = strsep(&tmp_val,",");
03280 moh_class = strsep(&tmp_val,",");
03281
03282 activateon = strsep(&activatedby, "/");
03283
03284
03285 if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
03286 ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
03287 app, exten, activateon, var->name);
03288 continue;
03289 }
03290
03291 AST_LIST_LOCK(&feature_list);
03292 if ((feature = find_dynamic_feature(var->name))) {
03293 AST_LIST_UNLOCK(&feature_list);
03294 ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
03295 continue;
03296 }
03297 AST_LIST_UNLOCK(&feature_list);
03298
03299 if (!(feature = ast_calloc(1, sizeof(*feature))))
03300 continue;
03301
03302 ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
03303 ast_copy_string(feature->app, app, FEATURE_APP_LEN);
03304 ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
03305
03306 if (app_args)
03307 ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
03308
03309 if (moh_class)
03310 ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
03311
03312 ast_copy_string(feature->exten, exten, sizeof(feature->exten));
03313 feature->operation = feature_exec_app;
03314 ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
03315
03316
03317 if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
03318 ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
03319 else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
03320 ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
03321 else {
03322 ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
03323 " must be 'self', or 'peer'\n", var->name);
03324 continue;
03325 }
03326
03327 if (ast_strlen_zero(activatedby))
03328 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
03329 else if (!strcasecmp(activatedby, "caller"))
03330 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
03331 else if (!strcasecmp(activatedby, "callee"))
03332 ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
03333 else if (!strcasecmp(activatedby, "both"))
03334 ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
03335 else {
03336 ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
03337 " must be 'caller', or 'callee', or 'both'\n", var->name);
03338 continue;
03339 }
03340
03341 ast_register_feature(feature);
03342
03343 if (option_verbose >= 1)
03344 ast_verbose(VERBOSE_PREFIX_2 "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, app, app_args, exten);
03345 }
03346 ast_config_destroy(cfg);
03347
03348
03349 if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
03350 if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar))
03351 notify_metermaids(old_parking_ext, old_parking_con);
03352 if (option_debug)
03353 ast_log(LOG_DEBUG, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
03354 }
03355
03356 if (!(con = ast_context_find(parking_con)) && !(con = ast_context_create(NULL, parking_con, registrar))) {
03357 ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
03358 return -1;
03359 }
03360 res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
03361 if (parkaddhints)
03362 park_add_hints(parking_con, parking_start, parking_stop);
03363 if (!res)
03364 notify_metermaids(ast_parking_ext(), parking_con);
03365 return res;
03366
03367 }
03368
03369 static char *app_bridge = "Bridge";
03370 static char *bridge_synopsis = "Bridge two channels";
03371 static char *bridge_descrip =
03372 "Usage: Bridge(channel[|options])\n"
03373 " Allows the ability to bridge two channels via the dialplan.\n"
03374 "The current channel is bridged to the specified 'channel'.\n"
03375 "The following options are supported:\n"
03376 " p - Play a courtesy tone to 'channel'.\n"
03377 "BRIDGERESULT dial plan variable will contain SUCCESS, FAILURE, LOOP, NONEXISTENT or INCOMPATIBLE.\n";
03378
03379 enum {
03380 BRIDGE_OPT_PLAYTONE = (1 << 0),
03381 };
03382
03383 AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
03384 AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE)
03385 END_OPTIONS );
03386
03387 static int bridge_exec(struct ast_channel *chan, void *data)
03388 {
03389 struct ast_module_user *u;
03390 struct ast_channel *current_dest_chan, *final_dest_chan;
03391 char *tmp_data = NULL;
03392 struct ast_flags opts = { 0, };
03393 struct ast_bridge_config bconfig = { { 0, }, };
03394
03395 AST_DECLARE_APP_ARGS(args,
03396 AST_APP_ARG(dest_chan);
03397 AST_APP_ARG(options);
03398 );
03399
03400 if (ast_strlen_zero(data)) {
03401 ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
03402 return -1;
03403 }
03404
03405 u = ast_module_user_add(chan);
03406
03407 tmp_data = ast_strdupa(data);
03408 AST_STANDARD_APP_ARGS(args, tmp_data);
03409 if (!ast_strlen_zero(args.options))
03410 ast_app_parse_options(bridge_exec_options, &opts, NULL, args.options);
03411
03412
03413 if (!strncmp(chan->name, args.dest_chan,
03414 strlen(chan->name) < strlen(args.dest_chan) ?
03415 strlen(chan->name) : strlen(args.dest_chan))) {
03416 ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
03417 manager_event(EVENT_FLAG_CALL, "BridgeExec",
03418 "Response: Failed\r\n"
03419 "Reason: Unable to bridge channel to itself\r\n"
03420 "Channel1: %s\r\n"
03421 "Channel2: %s\r\n",
03422 chan->name, args.dest_chan);
03423 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
03424 ast_module_user_remove(u);
03425 return 0;
03426 }
03427
03428
03429 if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan,
03430 strlen(args.dest_chan)))) {
03431 ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
03432 "cannot get its lock\n", args.dest_chan);
03433 manager_event(EVENT_FLAG_CALL, "BridgeExec",
03434 "Response: Failed\r\n"
03435 "Reason: Cannot grab end point\r\n"
03436 "Channel1: %s\r\n"
03437 "Channel2: %s\r\n", chan->name, args.dest_chan);
03438 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
03439 ast_module_user_remove(u);
03440 return 0;
03441 }
03442 ast_mutex_unlock(¤t_dest_chan->lock);
03443
03444
03445 if (current_dest_chan->_state != AST_STATE_UP)
03446 ast_answer(current_dest_chan);
03447
03448
03449 if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
03450 NULL, NULL, 0, "Bridge/%s", current_dest_chan->name))) {
03451 ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
03452 manager_event(EVENT_FLAG_CALL, "BridgeExec",
03453 "Response: Failed\r\n"
03454 "Reason: cannot create placeholder\r\n"
03455 "Channel1: %s\r\n"
03456 "Channel2: %s\r\n", chan->name, args.dest_chan);
03457 }
03458 do_bridge_masquerade(current_dest_chan, final_dest_chan);
03459
03460
03461
03462 if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
03463 ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
03464 manager_event(EVENT_FLAG_CALL, "BridgeExec",
03465 "Response: Failed\r\n"
03466 "Reason: Could not make channels compatible for bridge\r\n"
03467 "Channel1: %s\r\n"
03468 "Channel2: %s\r\n", chan->name, final_dest_chan->name);
03469 ast_hangup(final_dest_chan);
03470 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
03471 ast_module_user_remove(u);
03472 return 0;
03473 }
03474
03475
03476 manager_event(EVENT_FLAG_CALL, "BridgeExec",
03477 "Response: Success\r\n"
03478 "Channel1: %s\r\n"
03479 "Channel2: %s\r\n", chan->name, final_dest_chan->name);
03480
03481
03482 if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) {
03483 if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) {
03484 if (ast_waitstream(final_dest_chan, "") < 0)
03485 ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
03486 }
03487 }
03488
03489
03490 ast_bridge_call(chan, final_dest_chan, &bconfig);
03491
03492
03493 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
03494 if (!ast_check_hangup(final_dest_chan)) {
03495 if (option_debug) {
03496 ast_log(LOG_DEBUG, "starting new PBX in %s,%s,%d for chan %s\n",
03497 final_dest_chan->context, final_dest_chan->exten,
03498 final_dest_chan->priority, final_dest_chan->name);
03499 }
03500
03501 if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
03502 ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name);
03503 ast_hangup(final_dest_chan);
03504 } else if (option_debug)
03505 ast_log(LOG_DEBUG, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
03506 } else {
03507 if (option_debug)
03508 ast_log(LOG_DEBUG, "hangup chan %s since the other endpoint has hung up\n", final_dest_chan->name);
03509 ast_hangup(final_dest_chan);
03510 }
03511
03512 ast_module_user_remove(u);
03513
03514 return 0;
03515 }
03516
03517 static int reload(void)
03518 {
03519 autoanswer_reregister_extensions();
03520 return load_config();
03521 }
03522
03523 static int load_module(void)
03524 {
03525 int res;
03526
03527 ast_register_application(app_bridge, bridge_exec, bridge_synopsis, bridge_descrip);
03528
03529 memset(parking_ext, 0, sizeof(parking_ext));
03530 memset(parking_con, 0, sizeof(parking_con));
03531
03532 if ((res = load_config()))
03533 return res;
03534 ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
03535 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
03536 ast_pthread_create(&holding_thread, NULL, do_holding_thread, NULL);
03537 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
03538 if (!res)
03539 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
03540 if (!res) {
03541 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
03542 ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
03543 "Park a channel", mandescr_park);
03544 ast_manager_register2("Bridge", EVENT_FLAG_COMMAND, action_bridge, "Bridge two channels already in the PBX", mandescr_bridge);
03545 }
03546
03547 res |= ast_register_application(holdedcall, retrieve_call_exec, synopsis, descrip);
03548 ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
03549 if (!res)
03550 res |= ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
03551 if (!res)
03552 res |= ast_register_application(autoanswer, autoanswer_exec, synopsis4, descrip4);
03553
03554 res |= ast_devstate_prov_add("Park", metermaidstate);
03555
03556 return res;
03557 }
03558
03559
03560 static int unload_module(void)
03561 {
03562 ast_module_user_hangup_all();
03563
03564 ast_manager_unregister("ParkedCalls");
03565 ast_manager_unregister("Bridge");
03566 ast_manager_unregister("Park");
03567 ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
03568 ast_unregister_application(parkcall);
03569 ast_unregister_application(app_bridge);
03570 ast_unregister_application(autoanswer);
03571 ast_unregister_application(autoanswerlogin);
03572 ast_unregister_application(holdedcall);
03573 ast_devstate_prov_del("Park");
03574 return ast_unregister_application(parkedcall);
03575 }
03576
03577 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Call Features Resource",
03578 .load = load_module,
03579 .unload = unload_module,
03580 .reload = reload,
03581 );