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 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 255505 $")
00036
00037 #include <sys/time.h>
00038 #include <sys/signal.h>
00039 #include <sys/stat.h>
00040 #include <netinet/in.h>
00041
00042 #include "asterisk/paths.h"
00043 #include "asterisk/lock.h"
00044 #include "asterisk/file.h"
00045 #include "asterisk/channel.h"
00046 #include "asterisk/pbx.h"
00047 #include "asterisk/module.h"
00048 #include "asterisk/translate.h"
00049 #include "asterisk/say.h"
00050 #include "asterisk/config.h"
00051 #include "asterisk/features.h"
00052 #include "asterisk/musiconhold.h"
00053 #include "asterisk/callerid.h"
00054 #include "asterisk/utils.h"
00055 #include "asterisk/app.h"
00056 #include "asterisk/causes.h"
00057 #include "asterisk/rtp.h"
00058 #include "asterisk/cdr.h"
00059 #include "asterisk/manager.h"
00060 #include "asterisk/privacy.h"
00061 #include "asterisk/stringfields.h"
00062 #include "asterisk/global_datastores.h"
00063 #include "asterisk/dsp.h"
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 static char *app = "Dial";
00466 static char *rapp = "RetryDial";
00467
00468 enum {
00469 OPT_ANNOUNCE = (1 << 0),
00470 OPT_RESETCDR = (1 << 1),
00471 OPT_DTMF_EXIT = (1 << 2),
00472 OPT_SENDDTMF = (1 << 3),
00473 OPT_FORCECLID = (1 << 4),
00474 OPT_GO_ON = (1 << 5),
00475 OPT_CALLEE_HANGUP = (1 << 6),
00476 OPT_CALLER_HANGUP = (1 << 7),
00477 OPT_DURATION_LIMIT = (1 << 9),
00478 OPT_MUSICBACK = (1 << 10),
00479 OPT_CALLEE_MACRO = (1 << 11),
00480 OPT_SCREEN_NOINTRO = (1 << 12),
00481 OPT_SCREEN_NOCLID = (1 << 13),
00482 OPT_ORIGINAL_CLID = (1 << 14),
00483 OPT_SCREENING = (1 << 15),
00484 OPT_PRIVACY = (1 << 16),
00485 OPT_RINGBACK = (1 << 17),
00486 OPT_DURATION_STOP = (1 << 18),
00487 OPT_CALLEE_TRANSFER = (1 << 19),
00488 OPT_CALLER_TRANSFER = (1 << 20),
00489 OPT_CALLEE_MONITOR = (1 << 21),
00490 OPT_CALLER_MONITOR = (1 << 22),
00491 OPT_GOTO = (1 << 23),
00492 OPT_OPERMODE = (1 << 24),
00493 OPT_CALLEE_PARK = (1 << 25),
00494 OPT_CALLER_PARK = (1 << 26),
00495 OPT_IGNORE_FORWARDING = (1 << 27),
00496 OPT_CALLEE_GOSUB = (1 << 28),
00497 OPT_CALLEE_MIXMONITOR = (1 << 29),
00498 OPT_CALLER_MIXMONITOR = (1 << 30),
00499 };
00500
00501 #define DIAL_STILLGOING (1 << 31)
00502 #define DIAL_NOFORWARDHTML ((uint64_t)1 << 32)
00503 #define OPT_CANCEL_ELSEWHERE ((uint64_t)1 << 33)
00504 #define OPT_PEER_H ((uint64_t)1 << 34)
00505 #define OPT_CALLEE_GO_ON ((uint64_t)1 << 35)
00506
00507 enum {
00508 OPT_ARG_ANNOUNCE = 0,
00509 OPT_ARG_SENDDTMF,
00510 OPT_ARG_GOTO,
00511 OPT_ARG_DURATION_LIMIT,
00512 OPT_ARG_MUSICBACK,
00513 OPT_ARG_CALLEE_MACRO,
00514 OPT_ARG_CALLEE_GOSUB,
00515 OPT_ARG_CALLEE_GO_ON,
00516 OPT_ARG_PRIVACY,
00517 OPT_ARG_DURATION_STOP,
00518 OPT_ARG_OPERMODE,
00519 OPT_ARG_SCREEN_NOINTRO,
00520
00521 OPT_ARG_ARRAY_SIZE,
00522 };
00523
00524 AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS
00525 AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE),
00526 AST_APP_OPTION('C', OPT_RESETCDR),
00527 AST_APP_OPTION('c', OPT_CANCEL_ELSEWHERE),
00528 AST_APP_OPTION('d', OPT_DTMF_EXIT),
00529 AST_APP_OPTION_ARG('D', OPT_SENDDTMF, OPT_ARG_SENDDTMF),
00530 AST_APP_OPTION('e', OPT_PEER_H),
00531 AST_APP_OPTION('f', OPT_FORCECLID),
00532 AST_APP_OPTION_ARG('F', OPT_CALLEE_GO_ON, OPT_ARG_CALLEE_GO_ON),
00533 AST_APP_OPTION('g', OPT_GO_ON),
00534 AST_APP_OPTION_ARG('G', OPT_GOTO, OPT_ARG_GOTO),
00535 AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
00536 AST_APP_OPTION('H', OPT_CALLER_HANGUP),
00537 AST_APP_OPTION('i', OPT_IGNORE_FORWARDING),
00538 AST_APP_OPTION('k', OPT_CALLEE_PARK),
00539 AST_APP_OPTION('K', OPT_CALLER_PARK),
00540 AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
00541 AST_APP_OPTION_ARG('m', OPT_MUSICBACK, OPT_ARG_MUSICBACK),
00542 AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO),
00543 AST_APP_OPTION_ARG('n', OPT_SCREEN_NOINTRO, OPT_ARG_SCREEN_NOINTRO),
00544 AST_APP_OPTION('N', OPT_SCREEN_NOCLID),
00545 AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
00546 AST_APP_OPTION_ARG('O', OPT_OPERMODE, OPT_ARG_OPERMODE),
00547 AST_APP_OPTION('p', OPT_SCREENING),
00548 AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
00549 AST_APP_OPTION('r', OPT_RINGBACK),
00550 AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
00551 AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
00552 AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
00553 AST_APP_OPTION_ARG('U', OPT_CALLEE_GOSUB, OPT_ARG_CALLEE_GOSUB),
00554 AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
00555 AST_APP_OPTION('W', OPT_CALLER_MONITOR),
00556 AST_APP_OPTION('x', OPT_CALLEE_MIXMONITOR),
00557 AST_APP_OPTION('X', OPT_CALLER_MIXMONITOR),
00558 END_OPTIONS );
00559
00560 #define CAN_EARLY_BRIDGE(flags,chan,peer) (!ast_test_flag64(flags, OPT_CALLEE_HANGUP | \
00561 OPT_CALLER_HANGUP | OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | \
00562 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | OPT_CALLEE_PARK | \
00563 OPT_CALLER_PARK | OPT_ANNOUNCE | OPT_CALLEE_MACRO | OPT_CALLEE_GOSUB) && \
00564 !chan->audiohooks && !peer->audiohooks)
00565
00566
00567
00568
00569 struct chanlist {
00570 struct chanlist *next;
00571 struct ast_channel *chan;
00572 uint64_t flags;
00573 };
00574
00575
00576 static void hanguptree(struct chanlist *outgoing, struct ast_channel *exception, int answered_elsewhere)
00577 {
00578
00579 struct chanlist *oo;
00580 while (outgoing) {
00581
00582 if (outgoing->chan && (outgoing->chan != exception)) {
00583 if (answered_elsewhere) {
00584
00585 ast_set_flag(outgoing->chan, AST_FLAG_ANSWERED_ELSEWHERE);
00586
00587 outgoing->chan->hangupcause = AST_CAUSE_ANSWERED_ELSEWHERE;
00588 }
00589 ast_hangup(outgoing->chan);
00590 }
00591 oo = outgoing;
00592 outgoing = outgoing->next;
00593 ast_free(oo);
00594 }
00595 }
00596
00597 #define AST_MAX_WATCHERS 256
00598
00599
00600
00601
00602 struct cause_args {
00603 struct ast_channel *chan;
00604 int busy;
00605 int congestion;
00606 int nochan;
00607 };
00608
00609 static void handle_cause(int cause, struct cause_args *num)
00610 {
00611 struct ast_cdr *cdr = num->chan->cdr;
00612
00613 switch(cause) {
00614 case AST_CAUSE_BUSY:
00615 if (cdr)
00616 ast_cdr_busy(cdr);
00617 num->busy++;
00618 break;
00619
00620 case AST_CAUSE_CONGESTION:
00621 if (cdr)
00622 ast_cdr_failed(cdr);
00623 num->congestion++;
00624 break;
00625
00626 case AST_CAUSE_NO_ROUTE_DESTINATION:
00627 case AST_CAUSE_UNREGISTERED:
00628 if (cdr)
00629 ast_cdr_failed(cdr);
00630 num->nochan++;
00631 break;
00632
00633 case AST_CAUSE_NO_ANSWER:
00634 if (cdr) {
00635 ast_cdr_noanswer(cdr);
00636 }
00637 break;
00638 case AST_CAUSE_NORMAL_CLEARING:
00639 break;
00640
00641 default:
00642 num->nochan++;
00643 break;
00644 }
00645 }
00646
00647
00648 #define S_REPLACE(s, new_val) \
00649 do { \
00650 if (s) \
00651 ast_free(s); \
00652 s = (new_val); \
00653 } while (0)
00654
00655 static int onedigit_goto(struct ast_channel *chan, const char *context, char exten, int pri)
00656 {
00657 char rexten[2] = { exten, '\0' };
00658
00659 if (context) {
00660 if (!ast_goto_if_exists(chan, context, rexten, pri))
00661 return 1;
00662 } else {
00663 if (!ast_goto_if_exists(chan, chan->context, rexten, pri))
00664 return 1;
00665 else if (!ast_strlen_zero(chan->macrocontext)) {
00666 if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri))
00667 return 1;
00668 }
00669 }
00670 return 0;
00671 }
00672
00673
00674 static const char *get_cid_name(char *name, int namelen, struct ast_channel *chan)
00675 {
00676 const char *context = S_OR(chan->macrocontext, chan->context);
00677 const char *exten = S_OR(chan->macroexten, chan->exten);
00678
00679 return ast_get_hint(NULL, 0, name, namelen, chan, context, exten) ? name : "";
00680 }
00681
00682 static void senddialevent(struct ast_channel *src, struct ast_channel *dst, const char *dialstring)
00683 {
00684 manager_event(EVENT_FLAG_CALL, "Dial",
00685 "SubEvent: Begin\r\n"
00686 "Channel: %s\r\n"
00687 "Destination: %s\r\n"
00688 "CallerIDNum: %s\r\n"
00689 "CallerIDName: %s\r\n"
00690 "UniqueID: %s\r\n"
00691 "DestUniqueID: %s\r\n"
00692 "Dialstring: %s\r\n",
00693 src->name, dst->name, S_OR(src->cid.cid_num, "<unknown>"),
00694 S_OR(src->cid.cid_name, "<unknown>"), src->uniqueid,
00695 dst->uniqueid, dialstring ? dialstring : "");
00696 }
00697
00698 static void senddialendevent(const struct ast_channel *src, const char *dialstatus)
00699 {
00700 manager_event(EVENT_FLAG_CALL, "Dial",
00701 "SubEvent: End\r\n"
00702 "Channel: %s\r\n"
00703 "UniqueID: %s\r\n"
00704 "DialStatus: %s\r\n",
00705 src->name, src->uniqueid, dialstatus);
00706 }
00707
00708
00709
00710
00711
00712
00713
00714 static void do_forward(struct chanlist *o,
00715 struct cause_args *num, struct ast_flags64 *peerflags, int single)
00716 {
00717 char tmpchan[256];
00718 struct ast_channel *original = o->chan;
00719 struct ast_channel *c = o->chan;
00720 struct ast_channel *in = num->chan;
00721 char *stuff;
00722 char *tech;
00723 int cause;
00724
00725 ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan));
00726 if ((stuff = strchr(tmpchan, '/'))) {
00727 *stuff++ = '\0';
00728 tech = tmpchan;
00729 } else {
00730 const char *forward_context;
00731 ast_channel_lock(c);
00732 forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT");
00733 if (ast_strlen_zero(forward_context)) {
00734 forward_context = NULL;
00735 }
00736 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context);
00737 ast_channel_unlock(c);
00738 stuff = tmpchan;
00739 tech = "Local";
00740 }
00741
00742 ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
00743
00744 if (ast_test_flag64(peerflags, OPT_IGNORE_FORWARDING)) {
00745 ast_verb(3, "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
00746 c = o->chan = NULL;
00747 cause = AST_CAUSE_BUSY;
00748 } else {
00749
00750 c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
00751 if (c) {
00752 if (single)
00753 ast_channel_make_compatible(o->chan, in);
00754 ast_channel_inherit_variables(in, o->chan);
00755 ast_channel_datastore_inherit(in, o->chan);
00756 } else
00757 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
00758 }
00759 if (!c) {
00760 ast_clear_flag64(o, DIAL_STILLGOING);
00761 handle_cause(cause, num);
00762 ast_hangup(original);
00763 } else {
00764 char *new_cid_num, *new_cid_name;
00765 struct ast_channel *src;
00766
00767 if (CAN_EARLY_BRIDGE(peerflags, c, in)) {
00768 ast_rtp_make_compatible(c, in, single);
00769 }
00770 if (ast_test_flag64(o, OPT_FORCECLID)) {
00771 new_cid_num = ast_strdup(S_OR(in->macroexten, in->exten));
00772 new_cid_name = NULL;
00773 src = c;
00774 } else {
00775 new_cid_num = ast_strdup(in->cid.cid_num);
00776 new_cid_name = ast_strdup(in->cid.cid_name);
00777 src = in;
00778 }
00779 ast_string_field_set(c, accountcode, src->accountcode);
00780 c->cdrflags = src->cdrflags;
00781 S_REPLACE(c->cid.cid_num, new_cid_num);
00782 S_REPLACE(c->cid.cid_name, new_cid_name);
00783
00784 if (in->cid.cid_ani) {
00785 S_REPLACE(c->cid.cid_ani, ast_strdup(in->cid.cid_ani));
00786 }
00787 S_REPLACE(c->cid.cid_rdnis, ast_strdup(S_OR(in->macroexten, in->exten)));
00788 if (ast_call(c, tmpchan, 0)) {
00789 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
00790 ast_clear_flag64(o, DIAL_STILLGOING);
00791 ast_hangup(original);
00792 ast_hangup(c);
00793 c = o->chan = NULL;
00794 num->nochan++;
00795 } else {
00796 senddialevent(in, c, stuff);
00797
00798 if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) {
00799 char cidname[AST_MAX_EXTENSION] = "";
00800 ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL);
00801 }
00802
00803 ast_hangup(original);
00804 }
00805 if (single) {
00806 ast_indicate(in, -1);
00807 }
00808 }
00809 }
00810
00811
00812 struct privacy_args {
00813 int sentringing;
00814 int privdb_val;
00815 char privcid[256];
00816 char privintro[1024];
00817 char status[256];
00818 };
00819
00820 static struct ast_channel *wait_for_answer(struct ast_channel *in,
00821 struct chanlist *outgoing, int *to, struct ast_flags64 *peerflags,
00822 struct privacy_args *pa,
00823 const struct cause_args *num_in, int *result)
00824 {
00825 struct cause_args num = *num_in;
00826 int prestart = num.busy + num.congestion + num.nochan;
00827 int orig = *to;
00828 struct ast_channel *peer = NULL;
00829
00830 int single = outgoing && !outgoing->next && !ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
00831 #ifdef HAVE_EPOLL
00832 struct chanlist *epollo;
00833 #endif
00834
00835 if (single) {
00836
00837 ast_deactivate_generator(in);
00838
00839 ast_channel_make_compatible(outgoing->chan, in);
00840 }
00841
00842 #ifdef HAVE_EPOLL
00843 for (epollo = outgoing; epollo; epollo = epollo->next)
00844 ast_poll_channel_add(in, epollo->chan);
00845 #endif
00846
00847 while (*to && !peer) {
00848 struct chanlist *o;
00849 int pos = 0;
00850 int numlines = prestart;
00851 struct ast_channel *winner;
00852 struct ast_channel *watchers[AST_MAX_WATCHERS];
00853
00854 watchers[pos++] = in;
00855 for (o = outgoing; o; o = o->next) {
00856
00857 if (ast_test_flag64(o, DIAL_STILLGOING) && o->chan)
00858 watchers[pos++] = o->chan;
00859 numlines++;
00860 }
00861 if (pos == 1) {
00862 if (numlines == (num.busy + num.congestion + num.nochan)) {
00863 ast_verb(2, "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
00864 if (num.busy)
00865 strcpy(pa->status, "BUSY");
00866 else if (num.congestion)
00867 strcpy(pa->status, "CONGESTION");
00868 else if (num.nochan)
00869 strcpy(pa->status, "CHANUNAVAIL");
00870 } else {
00871 ast_verb(3, "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
00872 }
00873 *to = 0;
00874 return NULL;
00875 }
00876 winner = ast_waitfor_n(watchers, pos, to);
00877 for (o = outgoing; o; o = o->next) {
00878 struct ast_frame *f;
00879 struct ast_channel *c = o->chan;
00880
00881 if (c == NULL)
00882 continue;
00883 if (ast_test_flag64(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) {
00884 if (!peer) {
00885 ast_verb(3, "%s answered %s\n", c->name, in->name);
00886 peer = c;
00887 ast_copy_flags64(peerflags, o,
00888 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
00889 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
00890 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
00891 OPT_CALLEE_PARK | OPT_CALLER_PARK |
00892 OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
00893 DIAL_NOFORWARDHTML);
00894 ast_string_field_set(c, dialcontext, "");
00895 ast_copy_string(c->exten, "", sizeof(c->exten));
00896 }
00897 continue;
00898 }
00899 if (c != winner)
00900 continue;
00901
00902 if (!ast_strlen_zero(c->call_forward)) {
00903 do_forward(o, &num, peerflags, single);
00904 continue;
00905 }
00906 f = ast_read(winner);
00907 if (!f) {
00908 in->hangupcause = c->hangupcause;
00909 #ifdef HAVE_EPOLL
00910 ast_poll_channel_del(in, c);
00911 #endif
00912 ast_hangup(c);
00913 c = o->chan = NULL;
00914 ast_clear_flag64(o, DIAL_STILLGOING);
00915 handle_cause(in->hangupcause, &num);
00916 continue;
00917 }
00918 if (f->frametype == AST_FRAME_CONTROL) {
00919 switch(f->subclass) {
00920 case AST_CONTROL_ANSWER:
00921
00922 if (!peer) {
00923 ast_verb(3, "%s answered %s\n", c->name, in->name);
00924 peer = c;
00925 if (peer->cdr) {
00926 peer->cdr->answer = ast_tvnow();
00927 peer->cdr->disposition = AST_CDR_ANSWERED;
00928 }
00929 ast_copy_flags64(peerflags, o,
00930 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
00931 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
00932 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
00933 OPT_CALLEE_PARK | OPT_CALLER_PARK |
00934 OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
00935 DIAL_NOFORWARDHTML);
00936 ast_string_field_set(c, dialcontext, "");
00937 ast_copy_string(c->exten, "", sizeof(c->exten));
00938 if (CAN_EARLY_BRIDGE(peerflags, in, peer))
00939
00940 ast_channel_early_bridge(in, peer);
00941 }
00942
00943 in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
00944 c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
00945 break;
00946 case AST_CONTROL_BUSY:
00947 ast_verb(3, "%s is busy\n", c->name);
00948 in->hangupcause = c->hangupcause;
00949 ast_hangup(c);
00950 c = o->chan = NULL;
00951 ast_clear_flag64(o, DIAL_STILLGOING);
00952 handle_cause(AST_CAUSE_BUSY, &num);
00953 break;
00954 case AST_CONTROL_CONGESTION:
00955 ast_verb(3, "%s is circuit-busy\n", c->name);
00956 in->hangupcause = c->hangupcause;
00957 ast_hangup(c);
00958 c = o->chan = NULL;
00959 ast_clear_flag64(o, DIAL_STILLGOING);
00960 handle_cause(AST_CAUSE_CONGESTION, &num);
00961 break;
00962 case AST_CONTROL_RINGING:
00963 ast_verb(3, "%s is ringing\n", c->name);
00964
00965 if (single && CAN_EARLY_BRIDGE(peerflags, in, c))
00966 ast_channel_early_bridge(in, c);
00967 if (!(pa->sentringing) && !ast_test_flag64(outgoing, OPT_MUSICBACK)) {
00968 ast_indicate(in, AST_CONTROL_RINGING);
00969 pa->sentringing++;
00970 }
00971 break;
00972 case AST_CONTROL_PROGRESS:
00973 ast_verb(3, "%s is making progress passing it to %s\n", c->name, in->name);
00974
00975 if (single && CAN_EARLY_BRIDGE(peerflags, in, c))
00976 ast_channel_early_bridge(in, c);
00977 if (!ast_test_flag64(outgoing, OPT_RINGBACK))
00978 if (single || (!single && !pa->sentringing)) {
00979 ast_indicate(in, AST_CONTROL_PROGRESS);
00980 }
00981 break;
00982 case AST_CONTROL_VIDUPDATE:
00983 ast_verb(3, "%s requested a video update, passing it to %s\n", c->name, in->name);
00984 ast_indicate(in, AST_CONTROL_VIDUPDATE);
00985 break;
00986 case AST_CONTROL_SRCUPDATE:
00987 ast_verb(3, "%s requested a source update, passing it to %s\n", c->name, in->name);
00988 ast_indicate(in, AST_CONTROL_SRCUPDATE);
00989 break;
00990 case AST_CONTROL_PROCEEDING:
00991 ast_verb(3, "%s is proceeding passing it to %s\n", c->name, in->name);
00992 if (single && CAN_EARLY_BRIDGE(peerflags, in, c))
00993 ast_channel_early_bridge(in, c);
00994 if (!ast_test_flag64(outgoing, OPT_RINGBACK))
00995 ast_indicate(in, AST_CONTROL_PROCEEDING);
00996 break;
00997 case AST_CONTROL_HOLD:
00998 ast_verb(3, "Call on %s placed on hold\n", c->name);
00999 ast_indicate(in, AST_CONTROL_HOLD);
01000 break;
01001 case AST_CONTROL_UNHOLD:
01002 ast_verb(3, "Call on %s left from hold\n", c->name);
01003 ast_indicate(in, AST_CONTROL_UNHOLD);
01004 break;
01005 case AST_CONTROL_OFFHOOK:
01006 case AST_CONTROL_FLASH:
01007
01008 break;
01009 case -1:
01010 if (!ast_test_flag64(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) {
01011 ast_verb(3, "%s stopped sounds\n", c->name);
01012 ast_indicate(in, -1);
01013 pa->sentringing = 0;
01014 }
01015 break;
01016 default:
01017 ast_debug(1, "Dunno what to do with control type %d\n", f->subclass);
01018 }
01019 } else if (single) {
01020 switch (f->frametype) {
01021 case AST_FRAME_VOICE:
01022 case AST_FRAME_IMAGE:
01023 case AST_FRAME_TEXT:
01024 if (ast_write(in, f)) {
01025 ast_log(LOG_WARNING, "Unable to write frame\n");
01026 }
01027 break;
01028 case AST_FRAME_HTML:
01029 if (!ast_test_flag64(outgoing, DIAL_NOFORWARDHTML) && ast_channel_sendhtml(in, f->subclass, f->data.ptr, f->datalen) == -1) {
01030 ast_log(LOG_WARNING, "Unable to send URL\n");
01031 }
01032 break;
01033 default:
01034 break;
01035 }
01036 }
01037 ast_frfree(f);
01038 }
01039 if (winner == in) {
01040 struct ast_frame *f = ast_read(in);
01041 #if 0
01042 if (f && (f->frametype != AST_FRAME_VOICE))
01043 printf("Frame type: %d, %d\n", f->frametype, f->subclass);
01044 else if (!f || (f->frametype != AST_FRAME_VOICE))
01045 printf("Hangup received on %s\n", in->name);
01046 #endif
01047 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
01048
01049 *to = -1;
01050 strcpy(pa->status, "CANCEL");
01051 ast_cdr_noanswer(in->cdr);
01052 if (f) {
01053 if (f->data.uint32) {
01054 in->hangupcause = f->data.uint32;
01055 }
01056 ast_frfree(f);
01057 }
01058 return NULL;
01059 }
01060
01061
01062 if (f->frametype == AST_FRAME_DTMF) {
01063 if (ast_test_flag64(peerflags, OPT_DTMF_EXIT)) {
01064 const char *context;
01065 ast_channel_lock(in);
01066 context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
01067 if (onedigit_goto(in, context, (char) f->subclass, 1)) {
01068 ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
01069 *to = 0;
01070 ast_cdr_noanswer(in->cdr);
01071 *result = f->subclass;
01072 strcpy(pa->status, "CANCEL");
01073 ast_frfree(f);
01074 ast_channel_unlock(in);
01075 return NULL;
01076 }
01077 ast_channel_unlock(in);
01078 }
01079
01080 if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) &&
01081 (f->subclass == '*')) {
01082 ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
01083 *to = 0;
01084 strcpy(pa->status, "CANCEL");
01085 ast_cdr_noanswer(in->cdr);
01086 ast_frfree(f);
01087 return NULL;
01088 }
01089 }
01090
01091
01092 if (single && (f->frametype == AST_FRAME_HTML) && !ast_test_flag64(outgoing, DIAL_NOFORWARDHTML))
01093 if (ast_channel_sendhtml(outgoing->chan, f->subclass, f->data.ptr, f->datalen) == -1)
01094 ast_log(LOG_WARNING, "Unable to send URL\n");
01095
01096 if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF_BEGIN) || (f->frametype == AST_FRAME_DTMF_END))) {
01097 if (ast_write(outgoing->chan, f))
01098 ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n");
01099 }
01100 if (single && (f->frametype == AST_FRAME_CONTROL) &&
01101 ((f->subclass == AST_CONTROL_HOLD) ||
01102 (f->subclass == AST_CONTROL_UNHOLD) ||
01103 (f->subclass == AST_CONTROL_VIDUPDATE) ||
01104 (f->subclass == AST_CONTROL_SRCUPDATE))) {
01105 ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
01106 ast_indicate_data(outgoing->chan, f->subclass, f->data.ptr, f->datalen);
01107 }
01108 ast_frfree(f);
01109 }
01110 if (!*to)
01111 ast_verb(3, "Nobody picked up in %d ms\n", orig);
01112 if (!*to || ast_check_hangup(in))
01113 ast_cdr_noanswer(in->cdr);
01114 }
01115
01116 #ifdef HAVE_EPOLL
01117 for (epollo = outgoing; epollo; epollo = epollo->next) {
01118 if (epollo->chan)
01119 ast_poll_channel_del(in, epollo->chan);
01120 }
01121 #endif
01122
01123 return peer;
01124 }
01125
01126 static void replace_macro_delimiter(char *s)
01127 {
01128 for (; *s; s++)
01129 if (*s == '^')
01130 *s = ',';
01131 }
01132
01133
01134 static int valid_priv_reply(struct ast_flags64 *opts, int res)
01135 {
01136 if (res < '1')
01137 return 0;
01138 if (ast_test_flag64(opts, OPT_PRIVACY) && res <= '5')
01139 return 1;
01140 if (ast_test_flag64(opts, OPT_SCREENING) && res <= '4')
01141 return 1;
01142 return 0;
01143 }
01144
01145 static int do_timelimit(struct ast_channel *chan, struct ast_bridge_config *config,
01146 char *parse, struct timeval *calldurationlimit)
01147 {
01148 char *stringp = ast_strdupa(parse);
01149 char *limit_str, *warning_str, *warnfreq_str;
01150 const char *var;
01151 int play_to_caller = 0, play_to_callee = 0;
01152 int delta;
01153
01154 limit_str = strsep(&stringp, ":");
01155 warning_str = strsep(&stringp, ":");
01156 warnfreq_str = strsep(&stringp, ":");
01157
01158 config->timelimit = atol(limit_str);
01159 if (warning_str)
01160 config->play_warning = atol(warning_str);
01161 if (warnfreq_str)
01162 config->warning_freq = atol(warnfreq_str);
01163
01164 if (!config->timelimit) {
01165 ast_log(LOG_WARNING, "Dial does not accept L(%s), hanging up.\n", limit_str);
01166 config->timelimit = config->play_warning = config->warning_freq = 0;
01167 config->warning_sound = NULL;
01168 return -1;
01169 } else if ( (delta = config->play_warning - config->timelimit) > 0) {
01170 int w = config->warning_freq;
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184 if (w == 0) {
01185 config->play_warning = 0;
01186 } else {
01187 config->play_warning -= w * ( 1 + (delta-1)/w );
01188 if (config->play_warning < 1)
01189 config->play_warning = config->warning_freq = 0;
01190 }
01191 }
01192
01193 ast_channel_lock(chan);
01194
01195 var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLER");
01196
01197 play_to_caller = var ? ast_true(var) : 1;
01198
01199 var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLEE");
01200 play_to_callee = var ? ast_true(var) : 0;
01201
01202 if (!play_to_caller && !play_to_callee)
01203 play_to_caller = 1;
01204
01205 var = pbx_builtin_getvar_helper(chan, "LIMIT_WARNING_FILE");
01206 config->warning_sound = !ast_strlen_zero(var) ? ast_strdup(var) : ast_strdup("timeleft");
01207
01208
01209
01210
01211
01212
01213
01214 var = pbx_builtin_getvar_helper(chan, "LIMIT_TIMEOUT_FILE");
01215 config->end_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
01216
01217 var = pbx_builtin_getvar_helper(chan, "LIMIT_CONNECT_FILE");
01218 config->start_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
01219
01220 ast_channel_unlock(chan);
01221
01222
01223 calldurationlimit->tv_sec = 0;
01224 calldurationlimit->tv_usec = 0;
01225
01226
01227 if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
01228 calldurationlimit->tv_sec = config->timelimit / 1000;
01229 calldurationlimit->tv_usec = (config->timelimit % 1000) * 1000;
01230 ast_verb(3, "Setting call duration limit to %.3lf seconds.\n",
01231 calldurationlimit->tv_sec + calldurationlimit->tv_usec / 1000000.0);
01232 config->timelimit = play_to_caller = play_to_callee =
01233 config->play_warning = config->warning_freq = 0;
01234 } else {
01235 ast_verb(3, "Limit Data for this call:\n");
01236 ast_verb(4, "timelimit = %ld\n", config->timelimit);
01237 ast_verb(4, "play_warning = %ld\n", config->play_warning);
01238 ast_verb(4, "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
01239 ast_verb(4, "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
01240 ast_verb(4, "warning_freq = %ld\n", config->warning_freq);
01241 ast_verb(4, "start_sound = %s\n", S_OR(config->start_sound, ""));
01242 ast_verb(4, "warning_sound = %s\n", config->warning_sound);
01243 ast_verb(4, "end_sound = %s\n", S_OR(config->end_sound, ""));
01244 }
01245 if (play_to_caller)
01246 ast_set_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
01247 if (play_to_callee)
01248 ast_set_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
01249 return 0;
01250 }
01251
01252 static int do_privacy(struct ast_channel *chan, struct ast_channel *peer,
01253 struct ast_flags64 *opts, char **opt_args, struct privacy_args *pa)
01254 {
01255
01256 int res2;
01257 int loopcount = 0;
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267 if (ast_test_flag64(opts, OPT_MUSICBACK) && !ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
01268 char *original_moh = ast_strdupa(chan->musicclass);
01269 ast_indicate(chan, -1);
01270 ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
01271 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
01272 ast_string_field_set(chan, musicclass, original_moh);
01273 } else if (ast_test_flag64(opts, OPT_RINGBACK)) {
01274 ast_indicate(chan, AST_CONTROL_RINGING);
01275 pa->sentringing++;
01276 }
01277
01278
01279 res2 = ast_autoservice_start(chan);
01280
01281 for (loopcount = 0; loopcount < 3; loopcount++) {
01282 if (res2 && loopcount == 0)
01283 break;
01284 if (!res2)
01285 res2 = ast_play_and_wait(peer, "priv-callpending");
01286 if (!valid_priv_reply(opts, res2))
01287 res2 = 0;
01288
01289
01290
01291 if (!res2)
01292 res2 = ast_play_and_wait(peer, pa->privintro);
01293 if (!valid_priv_reply(opts, res2))
01294 res2 = 0;
01295
01296 if (!res2) {
01297
01298 if (ast_test_flag64(opts, OPT_PRIVACY))
01299 res2 = ast_play_and_wait(peer, "priv-callee-options");
01300 if (ast_test_flag64(opts, OPT_SCREENING))
01301 res2 = ast_play_and_wait(peer, "screen-callee-options");
01302 }
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319 if (valid_priv_reply(opts, res2))
01320 break;
01321
01322 res2 = ast_play_and_wait(peer, "vm-sorry");
01323 }
01324
01325 if (ast_test_flag64(opts, OPT_MUSICBACK)) {
01326 ast_moh_stop(chan);
01327 } else if (ast_test_flag64(opts, OPT_RINGBACK)) {
01328 ast_indicate(chan, -1);
01329 pa->sentringing = 0;
01330 }
01331 ast_autoservice_stop(chan);
01332 if (ast_test_flag64(opts, OPT_PRIVACY) && (res2 >= '1' && res2 <= '5')) {
01333
01334 static const char *_val[] = { "ALLOW", "DENY", "TORTURE", "KILL", "ALLOW" };
01335 static const int _flag[] = { AST_PRIVACY_ALLOW, AST_PRIVACY_DENY, AST_PRIVACY_TORTURE, AST_PRIVACY_KILL, AST_PRIVACY_ALLOW};
01336 int i = res2 - '1';
01337 ast_verb(3, "--Set privacy database entry %s/%s to %s\n",
01338 opt_args[OPT_ARG_PRIVACY], pa->privcid, _val[i]);
01339 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], pa->privcid, _flag[i]);
01340 }
01341 switch (res2) {
01342 case '1':
01343 break;
01344 case '2':
01345 ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status));
01346 break;
01347 case '3':
01348 ast_copy_string(pa->status, "TORTURE", sizeof(pa->status));
01349 break;
01350 case '4':
01351 ast_copy_string(pa->status, "DONTCALL", sizeof(pa->status));
01352 break;
01353 case '5':
01354
01355 if (ast_test_flag64(opts, OPT_PRIVACY))
01356 break;
01357
01358 default:
01359
01360
01361
01362
01363 ast_log(LOG_NOTICE, "privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
01364
01365
01366 break;
01367 }
01368
01369 if (res2 == '1') {
01370
01371
01372 if (strncmp(pa->privcid, "NOCALLERID", 10) == 0 || ast_test_flag64(opts, OPT_SCREEN_NOINTRO)) {
01373 ast_filedelete(pa->privintro, NULL);
01374 if (ast_fileexists(pa->privintro, NULL, NULL) > 0)
01375 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa->privintro);
01376 else
01377 ast_verb(3, "Successfully deleted %s intro file\n", pa->privintro);
01378 }
01379 return 0;
01380 } else {
01381 ast_hangup(peer);
01382 return -1;
01383 }
01384 }
01385
01386
01387 static int setup_privacy_args(struct privacy_args *pa,
01388 struct ast_flags64 *opts, char *opt_args[], struct ast_channel *chan)
01389 {
01390 char callerid[60];
01391 int res;
01392 char *l;
01393 int silencethreshold;
01394
01395 if (!ast_strlen_zero(chan->cid.cid_num)) {
01396 l = ast_strdupa(chan->cid.cid_num);
01397 ast_shrink_phone_number(l);
01398 if (ast_test_flag64(opts, OPT_PRIVACY) ) {
01399 ast_verb(3, "Privacy DB is '%s', clid is '%s'\n", opt_args[OPT_ARG_PRIVACY], l);
01400 pa->privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l);
01401 } else {
01402 ast_verb(3, "Privacy Screening, clid is '%s'\n", l);
01403 pa->privdb_val = AST_PRIVACY_UNKNOWN;
01404 }
01405 } else {
01406 char *tnam, *tn2;
01407
01408 tnam = ast_strdupa(chan->name);
01409
01410 for (tn2 = tnam; *tn2; tn2++) {
01411 if (*tn2 == '/')
01412 *tn2 = '=';
01413 }
01414 ast_verb(3, "Privacy-- callerid is empty\n");
01415
01416 snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
01417 l = callerid;
01418 pa->privdb_val = AST_PRIVACY_UNKNOWN;
01419 }
01420
01421 ast_copy_string(pa->privcid, l, sizeof(pa->privcid));
01422
01423 if (strncmp(pa->privcid, "NOCALLERID", 10) != 0 && ast_test_flag64(opts, OPT_SCREEN_NOCLID)) {
01424
01425 ast_verb(3, "CallerID set (%s); N option set; Screening should be off\n", pa->privcid);
01426 pa->privdb_val = AST_PRIVACY_ALLOW;
01427 } else if (ast_test_flag64(opts, OPT_SCREEN_NOCLID) && strncmp(pa->privcid, "NOCALLERID", 10) == 0) {
01428 ast_verb(3, "CallerID blank; N option set; Screening should happen; dbval is %d\n", pa->privdb_val);
01429 }
01430
01431 if (pa->privdb_val == AST_PRIVACY_DENY) {
01432 ast_verb(3, "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
01433 ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status));
01434 return 0;
01435 } else if (pa->privdb_val == AST_PRIVACY_KILL) {
01436 ast_copy_string(pa->status, "DONTCALL", sizeof(pa->status));
01437 return 0;
01438 } else if (pa->privdb_val == AST_PRIVACY_TORTURE) {
01439 ast_copy_string(pa->status, "TORTURE", sizeof(pa->status));
01440 return 0;
01441 } else if (pa->privdb_val == AST_PRIVACY_UNKNOWN) {
01442
01443
01444
01445
01446
01447 snprintf(pa->privintro, sizeof(pa->privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR);
01448 if ((res = ast_mkdir(pa->privintro, 0755))) {
01449 ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(res));
01450 return -1;
01451 }
01452
01453 snprintf(pa->privintro, sizeof(pa->privintro), "priv-callerintros/%s", pa->privcid);
01454 if (ast_fileexists(pa->privintro, NULL, NULL ) > 0 && strncmp(pa->privcid, "NOCALLERID", 10) != 0) {
01455
01456
01457
01458 } else {
01459 int duration;
01460
01461
01462
01463
01464
01465
01466
01467 silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
01468 ast_answer(chan);
01469 res = ast_play_and_record(chan, "priv-recordintro", pa->privintro, 4, "gsm", &duration, silencethreshold, 2000, 0);
01470
01471
01472 if (res == -1) {
01473
01474 ast_filedelete(pa->privintro, NULL);
01475 if (ast_fileexists(pa->privintro, NULL, NULL) > 0)
01476 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa->privintro);
01477 else
01478 ast_verb(3, "Successfully deleted %s intro file\n", pa->privintro);
01479 return -1;
01480 }
01481 if (!ast_streamfile(chan, "vm-dialout", chan->language) )
01482 ast_waitstream(chan, "");
01483 }
01484 }
01485 return 1;
01486 }
01487
01488 static void end_bridge_callback(void *data)
01489 {
01490 char buf[80];
01491 time_t end;
01492 struct ast_channel *chan = data;
01493
01494 if (!chan->cdr) {
01495 return;
01496 }
01497
01498 time(&end);
01499
01500 ast_channel_lock(chan);
01501 if (chan->cdr->answer.tv_sec) {
01502 snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->answer.tv_sec);
01503 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf);
01504 }
01505
01506 if (chan->cdr->start.tv_sec) {
01507 snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->start.tv_sec);
01508 pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf);
01509 }
01510 ast_channel_unlock(chan);
01511 }
01512
01513 static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator) {
01514 bconfig->end_bridge_callback_data = originator;
01515 }
01516
01517 static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags64 *peerflags, int *continue_exec)
01518 {
01519 int res = -1;
01520 char *rest, *cur;
01521 struct chanlist *outgoing = NULL;
01522 struct ast_channel *peer;
01523 int to;
01524 struct cause_args num = { chan, 0, 0, 0 };
01525 int cause;
01526 char numsubst[256];
01527 char cidname[AST_MAX_EXTENSION] = "";
01528
01529 struct ast_bridge_config config = { { 0, } };
01530 struct timeval calldurationlimit = { 0, };
01531 char *dtmfcalled = NULL, *dtmfcalling = NULL;
01532 struct privacy_args pa = {
01533 .sentringing = 0,
01534 .privdb_val = 0,
01535 .status = "INVALIDARGS",
01536 };
01537 int sentringing = 0, moh = 0;
01538 const char *outbound_group = NULL;
01539 int result = 0;
01540 char *parse;
01541 int opermode = 0;
01542 int delprivintro = 0;
01543 AST_DECLARE_APP_ARGS(args,
01544 AST_APP_ARG(peers);
01545 AST_APP_ARG(timeout);
01546 AST_APP_ARG(options);
01547 AST_APP_ARG(url);
01548 );
01549 struct ast_flags64 opts = { 0, };
01550 char *opt_args[OPT_ARG_ARRAY_SIZE];
01551 struct ast_datastore *datastore = NULL;
01552 int fulldial = 0, num_dialed = 0;
01553
01554
01555 pbx_builtin_setvar_helper(chan, "DIALSTATUS", "");
01556 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", "");
01557 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", "");
01558 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", "");
01559 pbx_builtin_setvar_helper(chan, "DIALEDTIME", "");
01560
01561 if (ast_strlen_zero(data)) {
01562 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
01563 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01564 return -1;
01565 }
01566
01567 parse = ast_strdupa(data);
01568
01569 AST_STANDARD_APP_ARGS(args, parse);
01570
01571 if (!ast_strlen_zero(args.options) &&
01572 ast_app_parse_options64(dial_exec_options, &opts, opt_args, args.options)) {
01573 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01574 goto done;
01575 }
01576
01577 if (ast_strlen_zero(args.peers)) {
01578 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
01579 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01580 goto done;
01581 }
01582
01583
01584 if (ast_test_flag64(&opts, OPT_SCREEN_NOINTRO) && !ast_strlen_zero(opt_args[OPT_ARG_SCREEN_NOINTRO])) {
01585 delprivintro = atoi(opt_args[OPT_ARG_SCREEN_NOINTRO]);
01586
01587 if (delprivintro < 0 || delprivintro > 1) {
01588 ast_log(LOG_WARNING, "Unknown argument %d specified to n option, ignoring\n", delprivintro);
01589 delprivintro = 0;
01590 }
01591 }
01592
01593 if (ast_test_flag64(&opts, OPT_OPERMODE)) {
01594 opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]);
01595 ast_verb(3, "Setting operator services mode to %d.\n", opermode);
01596 }
01597
01598 if (ast_test_flag64(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
01599 calldurationlimit.tv_sec = atoi(opt_args[OPT_ARG_DURATION_STOP]);
01600 if (!calldurationlimit.tv_sec) {
01601 ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]);
01602 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01603 goto done;
01604 }
01605 ast_verb(3, "Setting call duration limit to %.3lf seconds.\n", calldurationlimit.tv_sec + calldurationlimit.tv_usec / 1000000.0);
01606 }
01607
01608 if (ast_test_flag64(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
01609 dtmfcalling = opt_args[OPT_ARG_SENDDTMF];
01610 dtmfcalled = strsep(&dtmfcalling, ":");
01611 }
01612
01613 if (ast_test_flag64(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
01614 if (do_timelimit(chan, &config, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit))
01615 goto done;
01616 }
01617
01618 if (ast_test_flag64(&opts, OPT_RESETCDR) && chan->cdr)
01619 ast_cdr_reset(chan->cdr, NULL);
01620 if (ast_test_flag64(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY]))
01621 opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten);
01622
01623 if (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) {
01624 res = setup_privacy_args(&pa, &opts, opt_args, chan);
01625 if (res <= 0)
01626 goto out;
01627 res = -1;
01628 }
01629
01630 if (ast_test_flag64(&opts, OPT_DTMF_EXIT)) {
01631 __ast_answer(chan, 0, 0);
01632 }
01633
01634 if (continue_exec)
01635 *continue_exec = 0;
01636
01637
01638
01639 ast_channel_lock(chan);
01640 if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP_ONCE"))) {
01641 outbound_group = ast_strdupa(outbound_group);
01642 pbx_builtin_setvar_helper(chan, "OUTBOUND_GROUP_ONCE", NULL);
01643 } else if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP"))) {
01644 outbound_group = ast_strdupa(outbound_group);
01645 }
01646 ast_channel_unlock(chan);
01647 ast_copy_flags64(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING | OPT_ANNOUNCE | OPT_CALLEE_MACRO | OPT_CALLEE_GOSUB);
01648
01649
01650 rest = args.peers;
01651 while ((cur = strsep(&rest, "&")) ) {
01652 struct chanlist *tmp;
01653 struct ast_channel *tc;
01654
01655 char *number = cur;
01656 char *interface = ast_strdupa(number);
01657 char *tech = strsep(&number, "/");
01658
01659 struct ast_dialed_interface *di;
01660 AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
01661 num_dialed++;
01662 if (!number) {
01663 ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n");
01664 goto out;
01665 }
01666 if (!(tmp = ast_calloc(1, sizeof(*tmp))))
01667 goto out;
01668 if (opts.flags) {
01669 ast_copy_flags64(tmp, &opts,
01670 OPT_CANCEL_ELSEWHERE |
01671 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
01672 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
01673 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
01674 OPT_CALLEE_PARK | OPT_CALLER_PARK |
01675 OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
01676 OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID);
01677 ast_set2_flag64(tmp, args.url, DIAL_NOFORWARDHTML);
01678 }
01679 ast_copy_string(numsubst, number, sizeof(numsubst));
01680
01681
01682 ast_channel_lock(chan);
01683 datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL);
01684 ast_channel_unlock(chan);
01685
01686 if (datastore)
01687 dialed_interfaces = datastore->data;
01688 else {
01689 if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) {
01690 ast_log(LOG_WARNING, "Unable to create channel datastore for dialed interfaces. Aborting!\n");
01691 ast_free(tmp);
01692 goto out;
01693 }
01694
01695 datastore->inheritance = DATASTORE_INHERIT_FOREVER;
01696
01697 if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {
01698 ast_datastore_free(datastore);
01699 ast_free(tmp);
01700 goto out;
01701 }
01702
01703 datastore->data = dialed_interfaces;
01704 AST_LIST_HEAD_INIT(dialed_interfaces);
01705
01706 ast_channel_lock(chan);
01707 ast_channel_datastore_add(chan, datastore);
01708 ast_channel_unlock(chan);
01709 }
01710
01711 AST_LIST_LOCK(dialed_interfaces);
01712 AST_LIST_TRAVERSE(dialed_interfaces, di, list) {
01713 if (!strcasecmp(di->interface, interface)) {
01714 ast_log(LOG_WARNING, "Skipping dialing interface '%s' again since it has already been dialed\n",
01715 di->interface);
01716 break;
01717 }
01718 }
01719 AST_LIST_UNLOCK(dialed_interfaces);
01720
01721 if (di) {
01722 fulldial++;
01723 ast_free(tmp);
01724 continue;
01725 }
01726
01727
01728
01729
01730
01731 if (strcasecmp(tech, "Local")) {
01732 if (!(di = ast_calloc(1, sizeof(*di) + strlen(interface)))) {
01733 AST_LIST_UNLOCK(dialed_interfaces);
01734 ast_free(tmp);
01735 goto out;
01736 }
01737 strcpy(di->interface, interface);
01738
01739 AST_LIST_LOCK(dialed_interfaces);
01740 AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
01741 AST_LIST_UNLOCK(dialed_interfaces);
01742 }
01743
01744 tc = ast_request(tech, chan->nativeformats, numsubst, &cause);
01745 if (!tc) {
01746
01747 ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n",
01748 tech, cause, ast_cause2str(cause));
01749 handle_cause(cause, &num);
01750 if (!rest)
01751 chan->hangupcause = cause;
01752 ast_free(tmp);
01753 continue;
01754 }
01755 pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", numsubst);
01756
01757
01758 if (CAN_EARLY_BRIDGE(peerflags, chan, tc)) {
01759 ast_rtp_make_compatible(tc, chan, !outgoing && !rest);
01760 }
01761
01762
01763 ast_channel_inherit_variables(chan, tc);
01764 ast_channel_datastore_inherit(chan, tc);
01765
01766 tc->appl = "AppDial";
01767 tc->data = "(Outgoing Line)";
01768 memset(&tc->whentohangup, 0, sizeof(tc->whentohangup));
01769
01770 S_REPLACE(tc->cid.cid_num, ast_strdup(chan->cid.cid_num));
01771 S_REPLACE(tc->cid.cid_name, ast_strdup(chan->cid.cid_name));
01772 S_REPLACE(tc->cid.cid_ani, ast_strdup(chan->cid.cid_ani));
01773 S_REPLACE(tc->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis));
01774
01775 ast_string_field_set(tc, accountcode, chan->accountcode);
01776 tc->cdrflags = chan->cdrflags;
01777 if (ast_strlen_zero(tc->musicclass))
01778 ast_string_field_set(tc, musicclass, chan->musicclass);
01779
01780 tc->cid.cid_pres = chan->cid.cid_pres;
01781 tc->cid.cid_ton = chan->cid.cid_ton;
01782 tc->cid.cid_tns = chan->cid.cid_tns;
01783 tc->cid.cid_ani2 = chan->cid.cid_ani2;
01784 tc->adsicpe = chan->adsicpe;
01785 tc->transfercapability = chan->transfercapability;
01786
01787
01788 if (outbound_group)
01789 ast_app_group_set_channel(tc, outbound_group);
01790
01791 if (ast_test_flag(chan, AST_FLAG_ANSWERED_ELSEWHERE))
01792 ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE);
01793
01794
01795 if (ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE))
01796 ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE);
01797
01798
01799
01800 ast_string_field_set(tc, dialcontext, ast_strlen_zero(chan->macrocontext) ? chan->context : chan->macrocontext);
01801 if (!ast_strlen_zero(chan->macroexten))
01802 ast_copy_string(tc->exten, chan->macroexten, sizeof(tc->exten));
01803 else
01804 ast_copy_string(tc->exten, chan->exten, sizeof(tc->exten));
01805
01806 res = ast_call(tc, numsubst, 0);
01807
01808
01809 if (chan->cdr)
01810 ast_cdr_setdestchan(chan->cdr, tc->name);
01811
01812
01813 if (res) {
01814
01815 ast_debug(1, "ast call on peer returned %d\n", res);
01816 ast_verb(3, "Couldn't call %s\n", numsubst);
01817 if (tc->hangupcause) {
01818 chan->hangupcause = tc->hangupcause;
01819 }
01820 ast_hangup(tc);
01821 tc = NULL;
01822 ast_free(tmp);
01823 continue;
01824 } else {
01825 senddialevent(chan, tc, numsubst);
01826 ast_verb(3, "Called %s\n", numsubst);
01827 if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID))
01828 ast_set_callerid(tc, S_OR(chan->macroexten, chan->exten), get_cid_name(cidname, sizeof(cidname), chan), NULL);
01829 }
01830
01831
01832
01833 ast_set_flag64(tmp, DIAL_STILLGOING);
01834 tmp->chan = tc;
01835 tmp->next = outgoing;
01836 outgoing = tmp;
01837
01838 if (outgoing->chan->_state == AST_STATE_UP)
01839 break;
01840 }
01841
01842 if (ast_strlen_zero(args.timeout)) {
01843 to = -1;
01844 } else {
01845 to = atoi(args.timeout);
01846 if (to > 0)
01847 to *= 1000;
01848 else {
01849 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'. Setting timeout to infinite\n", args.timeout);
01850 to = -1;
01851 }
01852 }
01853
01854 if (!outgoing) {
01855 strcpy(pa.status, "CHANUNAVAIL");
01856 if (fulldial == num_dialed) {
01857 res = -1;
01858 goto out;
01859 }
01860 } else {
01861
01862 strcpy(pa.status, "NOANSWER");
01863 if (ast_test_flag64(outgoing, OPT_MUSICBACK)) {
01864 moh = 1;
01865 if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
01866 char *original_moh = ast_strdupa(chan->musicclass);
01867 ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
01868 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
01869 ast_string_field_set(chan, musicclass, original_moh);
01870 } else {
01871 ast_moh_start(chan, NULL, NULL);
01872 }
01873 ast_indicate(chan, AST_CONTROL_PROGRESS);
01874 } else if (ast_test_flag64(outgoing, OPT_RINGBACK)) {
01875 ast_indicate(chan, AST_CONTROL_RINGING);
01876 sentringing++;
01877 }
01878 }
01879
01880 peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result);
01881
01882
01883
01884
01885
01886
01887
01888 if (!ast_channel_datastore_remove(chan, datastore))
01889 ast_datastore_free(datastore);
01890 if (!peer) {
01891 if (result) {
01892 res = result;
01893 } else if (to) {
01894 res = -1;
01895 } else {
01896 res = 0;
01897 }
01898
01899
01900
01901 if (chan->hangupcause == AST_CAUSE_INVALID_NUMBER_FORMAT) {
01902 res = AST_PBX_INCOMPLETE;
01903 }
01904
01905
01906 } else {
01907 const char *number;
01908
01909 strcpy(pa.status, "ANSWER");
01910 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01911
01912
01913
01914 hanguptree(outgoing, peer, 1);
01915 outgoing = NULL;
01916
01917 if (chan->cdr)
01918 ast_cdr_setdestchan(chan->cdr, peer->name);
01919 if (peer->name)
01920 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
01921
01922 ast_channel_lock(peer);
01923 number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
01924 if (!number)
01925 number = numsubst;
01926 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
01927 ast_channel_unlock(peer);
01928
01929 if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
01930 ast_debug(1, "app_dial: sendurl=%s.\n", args.url);
01931 ast_channel_sendurl( peer, args.url );
01932 }
01933 if ( (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) && pa.privdb_val == AST_PRIVACY_UNKNOWN) {
01934 if (do_privacy(chan, peer, &opts, opt_args, &pa)) {
01935 res = 0;
01936 goto out;
01937 }
01938 }
01939 if (!ast_test_flag64(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) {
01940 res = 0;
01941 } else {
01942 int digit = 0;
01943 struct ast_channel *chans[2];
01944 struct ast_channel *active_chan;
01945
01946 chans[0] = chan;
01947 chans[1] = peer;
01948
01949
01950
01951
01952 res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language);
01953 if (res) {
01954 res = 0;
01955 ast_log(LOG_ERROR, "error streaming file '%s' to callee\n", opt_args[OPT_ARG_ANNOUNCE]);
01956 }
01957
01958 ast_set_flag(peer, AST_FLAG_END_DTMF_ONLY);
01959 while (peer->stream) {
01960 int ms;
01961
01962 ms = ast_sched_wait(peer->sched);
01963
01964 if (ms < 0 && !peer->timingfunc) {
01965 ast_stopstream(peer);
01966 break;
01967 }
01968 if (ms < 0)
01969 ms = 1000;
01970
01971 active_chan = ast_waitfor_n(chans, 2, &ms);
01972 if (active_chan) {
01973 struct ast_frame *fr = ast_read(active_chan);
01974 if (!fr) {
01975 ast_hangup(peer);
01976 res = -1;
01977 goto done;
01978 }
01979 switch(fr->frametype) {
01980 case AST_FRAME_DTMF_END:
01981 digit = fr->subclass;
01982 if (active_chan == peer && strchr(AST_DIGIT_ANY, res)) {
01983 ast_stopstream(peer);
01984 res = ast_senddigit(chan, digit, 0);
01985 }
01986 break;
01987 case AST_FRAME_CONTROL:
01988 switch (fr->subclass) {
01989 case AST_CONTROL_HANGUP:
01990 ast_frfree(fr);
01991 ast_hangup(peer);
01992 res = -1;
01993 goto done;
01994 default:
01995 break;
01996 }
01997 break;
01998 default:
01999
02000 break;
02001 }
02002 ast_frfree(fr);
02003 }
02004 ast_sched_runq(peer->sched);
02005 }
02006 ast_clear_flag(peer, AST_FLAG_END_DTMF_ONLY);
02007 }
02008
02009 if (chan && peer && ast_test_flag64(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) {
02010 replace_macro_delimiter(opt_args[OPT_ARG_GOTO]);
02011 ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
02012
02013 ast_copy_string(peer->context, chan->context, sizeof(peer->context));
02014 ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten));
02015 peer->priority = chan->priority + 2;
02016 ast_pbx_start(peer);
02017 hanguptree(outgoing, NULL, ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE) ? 1 : 0);
02018 if (continue_exec)
02019 *continue_exec = 1;
02020 res = 0;
02021 goto done;
02022 }
02023
02024 if (ast_test_flag64(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) {
02025 struct ast_app *theapp;
02026 const char *macro_result;
02027
02028 res = ast_autoservice_start(chan);
02029 if (res) {
02030 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
02031 res = -1;
02032 }
02033
02034 theapp = pbx_findapp("Macro");
02035
02036 if (theapp && !res) {
02037
02038 ast_copy_string(peer->context, chan->context, sizeof(peer->context));
02039 ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten));
02040
02041 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]);
02042 res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]);
02043 ast_debug(1, "Macro exited with status %d\n", res);
02044 res = 0;
02045 } else {
02046 ast_log(LOG_ERROR, "Could not find application Macro\n");
02047 res = -1;
02048 }
02049
02050 if (ast_autoservice_stop(chan) < 0) {
02051 res = -1;
02052 }
02053
02054 ast_channel_lock(peer);
02055
02056 if (!res && (macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
02057 char *macro_transfer_dest;
02058
02059 if (!strcasecmp(macro_result, "BUSY")) {
02060 ast_copy_string(pa.status, macro_result, sizeof(pa.status));
02061 ast_set_flag64(peerflags, OPT_GO_ON);
02062 res = -1;
02063 } else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
02064 ast_copy_string(pa.status, macro_result, sizeof(pa.status));
02065 ast_set_flag64(peerflags, OPT_GO_ON);
02066 res = -1;
02067 } else if (!strcasecmp(macro_result, "CONTINUE")) {
02068
02069
02070
02071
02072 ast_set_flag64(peerflags, OPT_GO_ON);
02073 res = -1;
02074 } else if (!strcasecmp(macro_result, "ABORT")) {
02075
02076 res = -1;
02077 } else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
02078 res = -1;
02079
02080 if (strchr(macro_transfer_dest, '^')) {
02081 replace_macro_delimiter(macro_transfer_dest);
02082 if (!ast_parseable_goto(chan, macro_transfer_dest))
02083 ast_set_flag64(peerflags, OPT_GO_ON);
02084 }
02085 }
02086 }
02087
02088 ast_channel_unlock(peer);
02089 }
02090
02091 if (ast_test_flag64(&opts, OPT_CALLEE_GOSUB) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GOSUB])) {
02092 struct ast_app *theapp;
02093 const char *gosub_result;
02094 char *gosub_args, *gosub_argstart;
02095 int res9 = -1;
02096
02097 res9 = ast_autoservice_start(chan);
02098 if (res9) {
02099 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
02100 res9 = -1;
02101 }
02102
02103 theapp = pbx_findapp("Gosub");
02104
02105 if (theapp && !res9) {
02106 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GOSUB]);
02107
02108
02109 ast_copy_string(peer->context, "app_dial_gosub_virtual_context", sizeof(peer->context));
02110 ast_copy_string(peer->exten, "s", sizeof(peer->exten));
02111 peer->priority = 0;
02112
02113 gosub_argstart = strchr(opt_args[OPT_ARG_CALLEE_GOSUB], ',');
02114 if (gosub_argstart) {
02115 *gosub_argstart = 0;
02116 if (asprintf(&gosub_args, "%s,s,1(%s)", opt_args[OPT_ARG_CALLEE_GOSUB], gosub_argstart + 1) < 0) {
02117 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
02118 gosub_args = NULL;
02119 }
02120 *gosub_argstart = ',';
02121 } else {
02122 if (asprintf(&gosub_args, "%s,s,1", opt_args[OPT_ARG_CALLEE_GOSUB]) < 0) {
02123 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
02124 gosub_args = NULL;
02125 }
02126 }
02127
02128 if (gosub_args) {
02129 res9 = pbx_exec(peer, theapp, gosub_args);
02130 if (!res9) {
02131 struct ast_pbx_args args;
02132
02133 memset(&args, 0, sizeof(args));
02134 args.no_hangup_chan = 1;
02135 ast_pbx_run_args(peer, &args);
02136 }
02137 ast_free(gosub_args);
02138 ast_debug(1, "Gosub exited with status %d\n", res9);
02139 } else {
02140 ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n");
02141 }
02142
02143 } else if (!res9) {
02144 ast_log(LOG_ERROR, "Could not find application Gosub\n");
02145 res9 = -1;
02146 }
02147
02148 if (ast_autoservice_stop(chan) < 0) {
02149 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
02150 res9 = -1;
02151 }
02152
02153 ast_channel_lock(peer);
02154
02155 if (!res9 && (gosub_result = pbx_builtin_getvar_helper(peer, "GOSUB_RESULT"))) {
02156 char *gosub_transfer_dest;
02157
02158 if (!strcasecmp(gosub_result, "BUSY")) {
02159 ast_copy_string(pa.status, gosub_result, sizeof(pa.status));
02160 ast_set_flag64(peerflags, OPT_GO_ON);
02161 res = -1;
02162 } else if (!strcasecmp(gosub_result, "CONGESTION") || !strcasecmp(gosub_result, "CHANUNAVAIL")) {
02163 ast_copy_string(pa.status, gosub_result, sizeof(pa.status));
02164 ast_set_flag64(peerflags, OPT_GO_ON);
02165 res = -1;
02166 } else if (!strcasecmp(gosub_result, "CONTINUE")) {
02167
02168
02169
02170
02171 ast_set_flag64(peerflags, OPT_GO_ON);
02172 res = -1;
02173 } else if (!strcasecmp(gosub_result, "ABORT")) {
02174
02175 res = -1;
02176 } else if (!strncasecmp(gosub_result, "GOTO:", 5) && (gosub_transfer_dest = ast_strdupa(gosub_result + 5))) {
02177 res = -1;
02178
02179 if (strchr(gosub_transfer_dest, '^')) {
02180 replace_macro_delimiter(gosub_transfer_dest);
02181 if (!ast_parseable_goto(chan, gosub_transfer_dest))
02182 ast_set_flag64(peerflags, OPT_GO_ON);
02183 }
02184 }
02185 }
02186
02187 ast_channel_unlock(peer);
02188 }
02189
02190 if (!res) {
02191 if (!ast_tvzero(calldurationlimit)) {
02192 struct timeval whentohangup = calldurationlimit;
02193 peer->whentohangup = ast_tvadd(ast_tvnow(), whentohangup);
02194 }
02195 if (!ast_strlen_zero(dtmfcalled)) {
02196 ast_verb(3, "Sending DTMF '%s' to the called party.\n", dtmfcalled);
02197 res = ast_dtmf_stream(peer, chan, dtmfcalled, 250, 0);
02198 }
02199 if (!ast_strlen_zero(dtmfcalling)) {
02200 ast_verb(3, "Sending DTMF '%s' to the calling party.\n", dtmfcalling);
02201 res = ast_dtmf_stream(chan, peer, dtmfcalling, 250, 0);
02202 }
02203 }
02204
02205 if (res) {
02206 res = -1;
02207 } else {
02208 if (ast_test_flag64(peerflags, OPT_CALLEE_TRANSFER))
02209 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
02210 if (ast_test_flag64(peerflags, OPT_CALLER_TRANSFER))
02211 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
02212 if (ast_test_flag64(peerflags, OPT_CALLEE_HANGUP))
02213 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
02214 if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP))
02215 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
02216 if (ast_test_flag64(peerflags, OPT_CALLEE_MONITOR))
02217 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
02218 if (ast_test_flag64(peerflags, OPT_CALLER_MONITOR))
02219 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
02220 if (ast_test_flag64(peerflags, OPT_CALLEE_PARK))
02221 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
02222 if (ast_test_flag64(peerflags, OPT_CALLER_PARK))
02223 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
02224 if (ast_test_flag64(peerflags, OPT_CALLEE_MIXMONITOR))
02225 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMIXMON);
02226 if (ast_test_flag64(peerflags, OPT_CALLER_MIXMONITOR))
02227 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMIXMON);
02228 if (ast_test_flag64(peerflags, OPT_GO_ON))
02229 ast_set_flag(&(config.features_caller), AST_FEATURE_NO_H_EXTEN);
02230
02231 config.end_bridge_callback = end_bridge_callback;
02232 config.end_bridge_callback_data = chan;
02233 config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
02234
02235 if (moh) {
02236 moh = 0;
02237 ast_moh_stop(chan);
02238 } else if (sentringing) {
02239 sentringing = 0;
02240 ast_indicate(chan, -1);
02241 }
02242
02243 ast_deactivate_generator(chan);
02244
02245 res = ast_channel_make_compatible(chan, peer);
02246 if (res < 0) {
02247 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
02248 ast_hangup(peer);
02249 res = -1;
02250 goto done;
02251 }
02252 if (opermode) {
02253 struct oprmode oprmode;
02254
02255 oprmode.peer = peer;
02256 oprmode.mode = opermode;
02257
02258 ast_channel_setoption(chan, AST_OPTION_OPRMODE, &oprmode, sizeof(oprmode), 0);
02259 }
02260 res = ast_bridge_call(chan, peer, &config);
02261 }
02262
02263 strcpy(peer->context, chan->context);
02264
02265 if (ast_test_flag64(&opts, OPT_PEER_H) && ast_exists_extension(peer, peer->context, "h", 1, peer->cid.cid_num)) {
02266 int autoloopflag;
02267 int found;
02268 int res9;
02269
02270 strcpy(peer->exten, "h");
02271 peer->priority = 1;
02272 autoloopflag = ast_test_flag(peer, AST_FLAG_IN_AUTOLOOP);
02273 ast_set_flag(peer, AST_FLAG_IN_AUTOLOOP);
02274
02275 while ((res9 = ast_spawn_extension(peer, peer->context, peer->exten, peer->priority, peer->cid.cid_num, &found, 1)) == 0)
02276 peer->priority++;
02277
02278 if (found && res9) {
02279
02280 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
02281 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
02282 }
02283 ast_set2_flag(peer, autoloopflag, AST_FLAG_IN_AUTOLOOP);
02284 }
02285 if (!ast_check_hangup(peer) && ast_test_flag64(&opts, OPT_CALLEE_GO_ON) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) {
02286 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
02287 ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]);
02288 ast_pbx_start(peer);
02289 } else {
02290 if (!ast_check_hangup(chan))
02291 chan->hangupcause = peer->hangupcause;
02292 ast_hangup(peer);
02293 }
02294 }
02295 out:
02296 if (moh) {
02297 moh = 0;
02298 ast_moh_stop(chan);
02299 } else if (sentringing) {
02300 sentringing = 0;
02301 ast_indicate(chan, -1);
02302 }
02303
02304 if (delprivintro && ast_fileexists(pa.privintro, NULL, NULL) > 0) {
02305 ast_filedelete(pa.privintro, NULL);
02306 if (ast_fileexists(pa.privintro, NULL, NULL) > 0) {
02307 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa.privintro);
02308 } else {
02309 ast_verb(3, "Successfully deleted %s intro file\n", pa.privintro);
02310 }
02311 }
02312
02313 ast_channel_early_bridge(chan, NULL);
02314 hanguptree(outgoing, NULL, 0);
02315 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
02316 senddialendevent(chan, pa.status);
02317 ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);
02318
02319 if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_INCOMPLETE)) {
02320 if (!ast_tvzero(calldurationlimit))
02321 memset(&chan->whentohangup, 0, sizeof(chan->whentohangup));
02322 res = 0;
02323 }
02324
02325 done:
02326 if (config.warning_sound) {
02327 ast_free((char *)config.warning_sound);
02328 }
02329 if (config.end_sound) {
02330 ast_free((char *)config.end_sound);
02331 }
02332 if (config.start_sound) {
02333 ast_free((char *)config.start_sound);
02334 }
02335 return res;
02336 }
02337
02338 static int dial_exec(struct ast_channel *chan, void *data)
02339 {
02340 struct ast_flags64 peerflags;
02341
02342 memset(&peerflags, 0, sizeof(peerflags));
02343
02344 return dial_exec_full(chan, data, &peerflags, NULL);
02345 }
02346
02347 static int retrydial_exec(struct ast_channel *chan, void *data)
02348 {
02349 char *parse;
02350 const char *context = NULL;
02351 int sleepms = 0, loops = 0, res = -1;
02352 struct ast_flags64 peerflags = { 0, };
02353 AST_DECLARE_APP_ARGS(args,
02354 AST_APP_ARG(announce);
02355 AST_APP_ARG(sleep);
02356 AST_APP_ARG(retries);
02357 AST_APP_ARG(dialdata);
02358 );
02359
02360 if (ast_strlen_zero(data)) {
02361 ast_log(LOG_WARNING, "RetryDial requires an argument!\n");
02362 return -1;
02363 }
02364
02365 parse = ast_strdupa(data);
02366 AST_STANDARD_APP_ARGS(args, parse);
02367
02368 if (!ast_strlen_zero(args.sleep) && (sleepms = atoi(args.sleep)))
02369 sleepms *= 1000;
02370
02371 if (!ast_strlen_zero(args.retries)) {
02372 loops = atoi(args.retries);
02373 }
02374
02375 if (!args.dialdata) {
02376 ast_log(LOG_ERROR, "%s requires a 4th argument (dialdata)\n", rapp);
02377 goto done;
02378 }
02379
02380 if (sleepms < 1000)
02381 sleepms = 10000;
02382
02383 if (!loops)
02384 loops = -1;
02385
02386 ast_channel_lock(chan);
02387 context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT");
02388 context = !ast_strlen_zero(context) ? ast_strdupa(context) : NULL;
02389 ast_channel_unlock(chan);
02390
02391 res = 0;
02392 while (loops) {
02393 int continue_exec;
02394
02395 chan->data = "Retrying";
02396 if (ast_test_flag(chan, AST_FLAG_MOH))
02397 ast_moh_stop(chan);
02398
02399 res = dial_exec_full(chan, args.dialdata, &peerflags, &continue_exec);
02400 if (continue_exec)
02401 break;
02402
02403 if (res == 0) {
02404 if (ast_test_flag64(&peerflags, OPT_DTMF_EXIT)) {
02405 if (!ast_strlen_zero(args.announce)) {
02406 if (ast_fileexists(args.announce, NULL, chan->language) > 0) {
02407 if (!(res = ast_streamfile(chan, args.announce, chan->language)))
02408 ast_waitstream(chan, AST_DIGIT_ANY);
02409 } else
02410 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce);
02411 }
02412 if (!res && sleepms) {
02413 if (!ast_test_flag(chan, AST_FLAG_MOH))
02414 ast_moh_start(chan, NULL, NULL);
02415 res = ast_waitfordigit(chan, sleepms);
02416 }
02417 } else {
02418 if (!ast_strlen_zero(args.announce)) {
02419 if (ast_fileexists(args.announce, NULL, chan->language) > 0) {
02420 if (!(res = ast_streamfile(chan, args.announce, chan->language)))
02421 res = ast_waitstream(chan, "");
02422 } else
02423 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce);
02424 }
02425 if (sleepms) {
02426 if (!ast_test_flag(chan, AST_FLAG_MOH))
02427 ast_moh_start(chan, NULL, NULL);
02428 if (!res)
02429 res = ast_waitfordigit(chan, sleepms);
02430 }
02431 }
02432 }
02433
02434 if (res < 0 || res == AST_PBX_INCOMPLETE) {
02435 break;
02436 } else if (res > 0) {
02437 if (onedigit_goto(chan, context, (char) res, 1)) {
02438 res = 0;
02439 break;
02440 }
02441 }
02442 loops--;
02443 }
02444 if (loops == 0)
02445 res = 0;
02446 else if (res == 1)
02447 res = 0;
02448
02449 if (ast_test_flag(chan, AST_FLAG_MOH))
02450 ast_moh_stop(chan);
02451 done:
02452 return res;
02453 }
02454
02455 static int unload_module(void)
02456 {
02457 int res;
02458 struct ast_context *con;
02459
02460 res = ast_unregister_application(app);
02461 res |= ast_unregister_application(rapp);
02462
02463 if ((con = ast_context_find("app_dial_gosub_virtual_context"))) {
02464 ast_context_remove_extension2(con, "s", 1, NULL, 0);
02465 ast_context_destroy(con, "app_dial");
02466 }
02467
02468 return res;
02469 }
02470
02471 static int load_module(void)
02472 {
02473 int res;
02474 struct ast_context *con;
02475
02476 con = ast_context_find_or_create(NULL, NULL, "app_dial_gosub_virtual_context", "app_dial");
02477 if (!con)
02478 ast_log(LOG_ERROR, "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create\n");
02479 else
02480 ast_add_extension2(con, 1, "s", 1, NULL, NULL, "NoOp", ast_strdup(""), ast_free_ptr, "app_dial");
02481
02482 res = ast_register_application_xml(app, dial_exec);
02483 res |= ast_register_application_xml(rapp, retrydial_exec);
02484
02485 return res;
02486 }
02487
02488 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dialing Application");