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: 319528 $")
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 static int detect_disconnect(struct ast_channel *chan, char code, struct ast_str *featurecode);
00576
00577 static void hanguptree(struct chanlist *outgoing, struct ast_channel *exception, int answered_elsewhere)
00578 {
00579
00580 struct chanlist *oo;
00581 while (outgoing) {
00582
00583 if (outgoing->chan && (outgoing->chan != exception)) {
00584 if (answered_elsewhere) {
00585
00586 ast_set_flag(outgoing->chan, AST_FLAG_ANSWERED_ELSEWHERE);
00587
00588 outgoing->chan->hangupcause = AST_CAUSE_ANSWERED_ELSEWHERE;
00589 }
00590 ast_hangup(outgoing->chan);
00591 }
00592 oo = outgoing;
00593 outgoing = outgoing->next;
00594 ast_free(oo);
00595 }
00596 }
00597
00598 #define AST_MAX_WATCHERS 256
00599
00600
00601
00602
00603 struct cause_args {
00604 struct ast_channel *chan;
00605 int busy;
00606 int congestion;
00607 int nochan;
00608 };
00609
00610 static void handle_cause(int cause, struct cause_args *num)
00611 {
00612 struct ast_cdr *cdr = num->chan->cdr;
00613
00614 switch(cause) {
00615 case AST_CAUSE_BUSY:
00616 if (cdr)
00617 ast_cdr_busy(cdr);
00618 num->busy++;
00619 break;
00620
00621 case AST_CAUSE_CONGESTION:
00622 if (cdr)
00623 ast_cdr_failed(cdr);
00624 num->congestion++;
00625 break;
00626
00627 case AST_CAUSE_NO_ROUTE_DESTINATION:
00628 case AST_CAUSE_UNREGISTERED:
00629 if (cdr)
00630 ast_cdr_failed(cdr);
00631 num->nochan++;
00632 break;
00633
00634 case AST_CAUSE_NO_ANSWER:
00635 if (cdr) {
00636 ast_cdr_noanswer(cdr);
00637 }
00638 break;
00639 case AST_CAUSE_NORMAL_CLEARING:
00640 break;
00641
00642 default:
00643 num->nochan++;
00644 break;
00645 }
00646 }
00647
00648
00649 #define S_REPLACE(s, new_val) \
00650 do { \
00651 if (s) \
00652 ast_free(s); \
00653 s = (new_val); \
00654 } while (0)
00655
00656 static int onedigit_goto(struct ast_channel *chan, const char *context, char exten, int pri)
00657 {
00658 char rexten[2] = { exten, '\0' };
00659
00660 if (context) {
00661 if (!ast_goto_if_exists(chan, context, rexten, pri))
00662 return 1;
00663 } else {
00664 if (!ast_goto_if_exists(chan, chan->context, rexten, pri))
00665 return 1;
00666 else if (!ast_strlen_zero(chan->macrocontext)) {
00667 if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri))
00668 return 1;
00669 }
00670 }
00671 return 0;
00672 }
00673
00674
00675 static const char *get_cid_name(char *name, int namelen, struct ast_channel *chan)
00676 {
00677 const char *context = S_OR(chan->macrocontext, chan->context);
00678 const char *exten = S_OR(chan->macroexten, chan->exten);
00679
00680 return ast_get_hint(NULL, 0, name, namelen, chan, context, exten) ? name : "";
00681 }
00682
00683 static void senddialevent(struct ast_channel *src, struct ast_channel *dst, const char *dialstring)
00684 {
00685 manager_event(EVENT_FLAG_CALL, "Dial",
00686 "SubEvent: Begin\r\n"
00687 "Channel: %s\r\n"
00688 "Destination: %s\r\n"
00689 "CallerIDNum: %s\r\n"
00690 "CallerIDName: %s\r\n"
00691 "UniqueID: %s\r\n"
00692 "DestUniqueID: %s\r\n"
00693 "Dialstring: %s\r\n",
00694 src->name, dst->name, S_OR(src->cid.cid_num, "<unknown>"),
00695 S_OR(src->cid.cid_name, "<unknown>"), src->uniqueid,
00696 dst->uniqueid, dialstring ? dialstring : "");
00697 }
00698
00699 static void senddialendevent(const struct ast_channel *src, const char *dialstatus)
00700 {
00701 manager_event(EVENT_FLAG_CALL, "Dial",
00702 "SubEvent: End\r\n"
00703 "Channel: %s\r\n"
00704 "UniqueID: %s\r\n"
00705 "DialStatus: %s\r\n",
00706 src->name, src->uniqueid, dialstatus);
00707 }
00708
00709
00710
00711
00712
00713
00714
00715 static void do_forward(struct chanlist *o,
00716 struct cause_args *num, struct ast_flags64 *peerflags, int single)
00717 {
00718 char tmpchan[256];
00719 struct ast_channel *original = o->chan;
00720 struct ast_channel *c = o->chan;
00721 struct ast_channel *in = num->chan;
00722 char *stuff;
00723 char *tech;
00724 int cause;
00725
00726 ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan));
00727 if ((stuff = strchr(tmpchan, '/'))) {
00728 *stuff++ = '\0';
00729 tech = tmpchan;
00730 } else {
00731 const char *forward_context;
00732 ast_channel_lock(c);
00733 forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT");
00734 if (ast_strlen_zero(forward_context)) {
00735 forward_context = NULL;
00736 }
00737 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context);
00738 ast_channel_unlock(c);
00739 stuff = tmpchan;
00740 tech = "Local";
00741 }
00742
00743 ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
00744
00745 if (ast_test_flag64(peerflags, OPT_IGNORE_FORWARDING)) {
00746 ast_verb(3, "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
00747 c = o->chan = NULL;
00748 cause = AST_CAUSE_BUSY;
00749 } else {
00750
00751 c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
00752 if (c) {
00753 if (single)
00754 ast_channel_make_compatible(o->chan, in);
00755 ast_channel_inherit_variables(in, o->chan);
00756 ast_channel_datastore_inherit(in, o->chan);
00757 } else
00758 ast_log(LOG_NOTICE,
00759 "Forwarding failed to create channel to dial '%s/%s' (cause = %d)\n",
00760 tech, stuff, cause);
00761 }
00762 if (!c) {
00763 ast_clear_flag64(o, DIAL_STILLGOING);
00764 handle_cause(cause, num);
00765 ast_hangup(original);
00766 } else {
00767 char *new_cid_num, *new_cid_name;
00768 struct ast_channel *src;
00769
00770 if (CAN_EARLY_BRIDGE(peerflags, c, in)) {
00771 ast_rtp_make_compatible(c, in, single);
00772 }
00773 if (ast_test_flag64(o, OPT_FORCECLID)) {
00774 new_cid_num = ast_strdup(S_OR(in->macroexten, in->exten));
00775 new_cid_name = NULL;
00776 src = c;
00777 } else {
00778 new_cid_num = ast_strdup(in->cid.cid_num);
00779 new_cid_name = ast_strdup(in->cid.cid_name);
00780 src = in;
00781 }
00782 ast_string_field_set(c, accountcode, src->accountcode);
00783 c->cdrflags = src->cdrflags;
00784 S_REPLACE(c->cid.cid_num, new_cid_num);
00785 S_REPLACE(c->cid.cid_name, new_cid_name);
00786
00787 if (in->cid.cid_ani) {
00788 S_REPLACE(c->cid.cid_ani, ast_strdup(in->cid.cid_ani));
00789 }
00790 S_REPLACE(c->cid.cid_rdnis, ast_strdup(S_OR(in->macroexten, in->exten)));
00791 if (ast_call(c, stuff, 0)) {
00792 ast_log(LOG_NOTICE, "Forwarding failed to dial '%s/%s'\n",
00793 tech, stuff);
00794 ast_clear_flag64(o, DIAL_STILLGOING);
00795 ast_hangup(original);
00796 ast_hangup(c);
00797 c = o->chan = NULL;
00798 num->nochan++;
00799 } else {
00800 senddialevent(in, c, stuff);
00801
00802 if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) {
00803 char cidname[AST_MAX_EXTENSION] = "";
00804 ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL);
00805 }
00806
00807 ast_hangup(original);
00808 }
00809 if (single) {
00810 ast_indicate(in, -1);
00811 }
00812 }
00813 }
00814
00815
00816 struct privacy_args {
00817 int sentringing;
00818 int privdb_val;
00819 char privcid[256];
00820 char privintro[1024];
00821 char status[256];
00822 };
00823
00824 static struct ast_channel *wait_for_answer(struct ast_channel *in,
00825 struct chanlist *outgoing, int *to, struct ast_flags64 *peerflags,
00826 struct privacy_args *pa,
00827 const struct cause_args *num_in, int *result)
00828 {
00829 struct cause_args num = *num_in;
00830 int prestart = num.busy + num.congestion + num.nochan;
00831 int orig = *to;
00832 struct ast_channel *peer = NULL;
00833
00834 int single = outgoing && !outgoing->next && !ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
00835 #ifdef HAVE_EPOLL
00836 struct chanlist *epollo;
00837 #endif
00838 struct ast_str *featurecode = ast_str_alloca(FEATURE_MAX_LEN + 1);
00839 if (single) {
00840
00841 ast_deactivate_generator(in);
00842
00843 if (ast_channel_make_compatible(outgoing->chan, in) < 0) {
00844
00845
00846
00847
00848 *to = -1;
00849 strcpy(pa->status, "CONGESTION");
00850 ast_cdr_failed(in->cdr);
00851 return NULL;
00852 }
00853 }
00854
00855 #ifdef HAVE_EPOLL
00856 for (epollo = outgoing; epollo; epollo = epollo->next)
00857 ast_poll_channel_add(in, epollo->chan);
00858 #endif
00859
00860 while (*to && !peer) {
00861 struct chanlist *o;
00862 int pos = 0;
00863 int numlines = prestart;
00864 struct ast_channel *winner;
00865 struct ast_channel *watchers[AST_MAX_WATCHERS];
00866
00867 watchers[pos++] = in;
00868 for (o = outgoing; o; o = o->next) {
00869
00870 if (ast_test_flag64(o, DIAL_STILLGOING) && o->chan)
00871 watchers[pos++] = o->chan;
00872 numlines++;
00873 }
00874 if (pos == 1) {
00875 if (numlines == (num.busy + num.congestion + num.nochan)) {
00876 ast_verb(2, "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
00877 if (num.busy)
00878 strcpy(pa->status, "BUSY");
00879 else if (num.congestion)
00880 strcpy(pa->status, "CONGESTION");
00881 else if (num.nochan)
00882 strcpy(pa->status, "CHANUNAVAIL");
00883 } else {
00884 ast_verb(3, "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
00885 }
00886 *to = 0;
00887 return NULL;
00888 }
00889 winner = ast_waitfor_n(watchers, pos, to);
00890 for (o = outgoing; o; o = o->next) {
00891 struct ast_frame *f;
00892 struct ast_channel *c = o->chan;
00893
00894 if (c == NULL)
00895 continue;
00896 if (ast_test_flag64(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) {
00897 if (!peer) {
00898 ast_verb(3, "%s answered %s\n", c->name, in->name);
00899 peer = c;
00900 ast_copy_flags64(peerflags, o,
00901 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
00902 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
00903 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
00904 OPT_CALLEE_PARK | OPT_CALLER_PARK |
00905 OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
00906 DIAL_NOFORWARDHTML);
00907 ast_string_field_set(c, dialcontext, "");
00908 ast_copy_string(c->exten, "", sizeof(c->exten));
00909 }
00910 continue;
00911 }
00912 if (c != winner)
00913 continue;
00914
00915 if (!ast_strlen_zero(c->call_forward)) {
00916 do_forward(o, &num, peerflags, single);
00917 continue;
00918 }
00919 f = ast_read(winner);
00920 if (!f) {
00921 in->hangupcause = c->hangupcause;
00922 #ifdef HAVE_EPOLL
00923 ast_poll_channel_del(in, c);
00924 #endif
00925 ast_hangup(c);
00926 c = o->chan = NULL;
00927 ast_clear_flag64(o, DIAL_STILLGOING);
00928 handle_cause(in->hangupcause, &num);
00929 continue;
00930 }
00931 if (f->frametype == AST_FRAME_CONTROL) {
00932 switch(f->subclass) {
00933 case AST_CONTROL_ANSWER:
00934
00935 if (!peer) {
00936 ast_verb(3, "%s answered %s\n", c->name, in->name);
00937 peer = c;
00938 if (peer->cdr) {
00939 peer->cdr->answer = ast_tvnow();
00940 peer->cdr->disposition = AST_CDR_ANSWERED;
00941 }
00942 ast_copy_flags64(peerflags, o,
00943 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
00944 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
00945 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
00946 OPT_CALLEE_PARK | OPT_CALLER_PARK |
00947 OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
00948 DIAL_NOFORWARDHTML);
00949 ast_string_field_set(c, dialcontext, "");
00950 ast_copy_string(c->exten, "", sizeof(c->exten));
00951 if (CAN_EARLY_BRIDGE(peerflags, in, peer))
00952
00953 ast_channel_early_bridge(in, peer);
00954 }
00955
00956 in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
00957 c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
00958 break;
00959 case AST_CONTROL_BUSY:
00960 ast_verb(3, "%s is busy\n", c->name);
00961 in->hangupcause = c->hangupcause;
00962 ast_hangup(c);
00963 c = o->chan = NULL;
00964 ast_clear_flag64(o, DIAL_STILLGOING);
00965 handle_cause(AST_CAUSE_BUSY, &num);
00966 break;
00967 case AST_CONTROL_CONGESTION:
00968 ast_verb(3, "%s is circuit-busy\n", c->name);
00969 in->hangupcause = c->hangupcause;
00970 ast_hangup(c);
00971 c = o->chan = NULL;
00972 ast_clear_flag64(o, DIAL_STILLGOING);
00973 handle_cause(AST_CAUSE_CONGESTION, &num);
00974 break;
00975 case AST_CONTROL_RINGING:
00976 ast_verb(3, "%s is ringing\n", c->name);
00977
00978 if (single && CAN_EARLY_BRIDGE(peerflags, in, c))
00979 ast_channel_early_bridge(in, c);
00980 if (!(pa->sentringing) && !ast_test_flag64(outgoing, OPT_MUSICBACK)) {
00981 ast_indicate(in, AST_CONTROL_RINGING);
00982 pa->sentringing++;
00983 }
00984 break;
00985 case AST_CONTROL_PROGRESS:
00986 ast_verb(3, "%s is making progress passing it to %s\n", c->name, in->name);
00987
00988 if (single && CAN_EARLY_BRIDGE(peerflags, in, c))
00989 ast_channel_early_bridge(in, c);
00990 if (!ast_test_flag64(outgoing, OPT_RINGBACK))
00991 if (single || (!single && !pa->sentringing)) {
00992 ast_indicate(in, AST_CONTROL_PROGRESS);
00993 }
00994 break;
00995 case AST_CONTROL_VIDUPDATE:
00996 ast_verb(3, "%s requested a video update, passing it to %s\n", c->name, in->name);
00997 ast_indicate(in, AST_CONTROL_VIDUPDATE);
00998 break;
00999 case AST_CONTROL_SRCUPDATE:
01000 ast_verb(3, "%s requested a source update, passing it to %s\n", c->name, in->name);
01001 ast_indicate(in, AST_CONTROL_SRCUPDATE);
01002 break;
01003 case AST_CONTROL_PROCEEDING:
01004 ast_verb(3, "%s is proceeding passing it to %s\n", c->name, in->name);
01005 if (single && CAN_EARLY_BRIDGE(peerflags, in, c))
01006 ast_channel_early_bridge(in, c);
01007 if (!ast_test_flag64(outgoing, OPT_RINGBACK))
01008 ast_indicate(in, AST_CONTROL_PROCEEDING);
01009 break;
01010 case AST_CONTROL_HOLD:
01011 ast_verb(3, "Call on %s placed on hold\n", c->name);
01012 ast_indicate(in, AST_CONTROL_HOLD);
01013 break;
01014 case AST_CONTROL_UNHOLD:
01015 ast_verb(3, "Call on %s left from hold\n", c->name);
01016 ast_indicate(in, AST_CONTROL_UNHOLD);
01017 break;
01018 case AST_CONTROL_OFFHOOK:
01019 case AST_CONTROL_FLASH:
01020
01021 break;
01022 case -1:
01023 if (!ast_test_flag64(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) {
01024 ast_verb(3, "%s stopped sounds\n", c->name);
01025 ast_indicate(in, -1);
01026 pa->sentringing = 0;
01027 }
01028 break;
01029 default:
01030 ast_debug(1, "Dunno what to do with control type %d\n", f->subclass);
01031 }
01032 } else if (single) {
01033 switch (f->frametype) {
01034 case AST_FRAME_VOICE:
01035 case AST_FRAME_IMAGE:
01036 case AST_FRAME_TEXT:
01037 if (ast_write(in, f)) {
01038 ast_log(LOG_WARNING, "Unable to write frame\n");
01039 }
01040 break;
01041 case AST_FRAME_HTML:
01042 if (!ast_test_flag64(outgoing, DIAL_NOFORWARDHTML) && ast_channel_sendhtml(in, f->subclass, f->data.ptr, f->datalen) == -1) {
01043 ast_log(LOG_WARNING, "Unable to send URL\n");
01044 }
01045 break;
01046 default:
01047 break;
01048 }
01049 }
01050 ast_frfree(f);
01051 }
01052 if (winner == in) {
01053 struct ast_frame *f = ast_read(in);
01054 #if 0
01055 if (f && (f->frametype != AST_FRAME_VOICE))
01056 printf("Frame type: %d, %d\n", f->frametype, f->subclass);
01057 else if (!f || (f->frametype != AST_FRAME_VOICE))
01058 printf("Hangup received on %s\n", in->name);
01059 #endif
01060 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
01061
01062 *to = -1;
01063 strcpy(pa->status, "CANCEL");
01064 ast_cdr_noanswer(in->cdr);
01065 if (f) {
01066 if (f->data.uint32) {
01067 in->hangupcause = f->data.uint32;
01068 }
01069 ast_frfree(f);
01070 }
01071 return NULL;
01072 }
01073
01074
01075 if (f->frametype == AST_FRAME_DTMF) {
01076 if (ast_test_flag64(peerflags, OPT_DTMF_EXIT)) {
01077 const char *context;
01078 ast_channel_lock(in);
01079 context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
01080 if (onedigit_goto(in, context, (char) f->subclass, 1)) {
01081 ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
01082 *to = 0;
01083 ast_cdr_noanswer(in->cdr);
01084 *result = f->subclass;
01085 strcpy(pa->status, "CANCEL");
01086 ast_frfree(f);
01087 ast_channel_unlock(in);
01088 return NULL;
01089 }
01090 ast_channel_unlock(in);
01091 }
01092
01093 if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) &&
01094 detect_disconnect(in, f->subclass, featurecode)) {
01095 ast_verb(3, "User requested call disconnect.\n");
01096 *to = 0;
01097 strcpy(pa->status, "CANCEL");
01098 ast_cdr_noanswer(in->cdr);
01099 ast_frfree(f);
01100 return NULL;
01101 }
01102 }
01103
01104
01105 if (single && (f->frametype == AST_FRAME_HTML) && !ast_test_flag64(outgoing, DIAL_NOFORWARDHTML))
01106 if (ast_channel_sendhtml(outgoing->chan, f->subclass, f->data.ptr, f->datalen) == -1)
01107 ast_log(LOG_WARNING, "Unable to send URL\n");
01108
01109 if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF_BEGIN) || (f->frametype == AST_FRAME_DTMF_END))) {
01110 if (ast_write(outgoing->chan, f))
01111 ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n");
01112 }
01113 if (single && (f->frametype == AST_FRAME_CONTROL) &&
01114 ((f->subclass == AST_CONTROL_HOLD) ||
01115 (f->subclass == AST_CONTROL_UNHOLD) ||
01116 (f->subclass == AST_CONTROL_VIDUPDATE) ||
01117 (f->subclass == AST_CONTROL_SRCUPDATE))) {
01118 ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
01119 ast_indicate_data(outgoing->chan, f->subclass, f->data.ptr, f->datalen);
01120 }
01121 ast_frfree(f);
01122 }
01123 if (!*to)
01124 ast_verb(3, "Nobody picked up in %d ms\n", orig);
01125 if (!*to || ast_check_hangup(in))
01126 ast_cdr_noanswer(in->cdr);
01127 }
01128
01129 #ifdef HAVE_EPOLL
01130 for (epollo = outgoing; epollo; epollo = epollo->next) {
01131 if (epollo->chan)
01132 ast_poll_channel_del(in, epollo->chan);
01133 }
01134 #endif
01135
01136 return peer;
01137 }
01138
01139 static int detect_disconnect(struct ast_channel *chan, char code, struct ast_str *featurecode)
01140 {
01141 struct ast_flags features = { AST_FEATURE_DISCONNECT };
01142 struct ast_call_feature feature = { 0, };
01143 int res;
01144
01145 ast_str_append(&featurecode, 1, "%c", code);
01146
01147 res = ast_feature_detect(chan, &features, ast_str_buffer(featurecode), &feature);
01148
01149 if (res != AST_FEATURE_RETURN_STOREDIGITS) {
01150 ast_str_reset(featurecode);
01151 }
01152 if (feature.feature_mask & AST_FEATURE_DISCONNECT) {
01153 return 1;
01154 }
01155
01156 return 0;
01157 }
01158
01159 static void replace_macro_delimiter(char *s)
01160 {
01161 for (; *s; s++)
01162 if (*s == '^')
01163 *s = ',';
01164 }
01165
01166
01167 static int valid_priv_reply(struct ast_flags64 *opts, int res)
01168 {
01169 if (res < '1')
01170 return 0;
01171 if (ast_test_flag64(opts, OPT_PRIVACY) && res <= '5')
01172 return 1;
01173 if (ast_test_flag64(opts, OPT_SCREENING) && res <= '4')
01174 return 1;
01175 return 0;
01176 }
01177
01178 static int do_timelimit(struct ast_channel *chan, struct ast_bridge_config *config,
01179 char *parse, struct timeval *calldurationlimit)
01180 {
01181 char *stringp = ast_strdupa(parse);
01182 char *limit_str, *warning_str, *warnfreq_str;
01183 const char *var;
01184 int play_to_caller = 0, play_to_callee = 0;
01185 int delta;
01186
01187 limit_str = strsep(&stringp, ":");
01188 warning_str = strsep(&stringp, ":");
01189 warnfreq_str = strsep(&stringp, ":");
01190
01191 config->timelimit = atol(limit_str);
01192 if (warning_str)
01193 config->play_warning = atol(warning_str);
01194 if (warnfreq_str)
01195 config->warning_freq = atol(warnfreq_str);
01196
01197 if (!config->timelimit) {
01198 ast_log(LOG_WARNING, "Dial does not accept L(%s), hanging up.\n", limit_str);
01199 config->timelimit = config->play_warning = config->warning_freq = 0;
01200 config->warning_sound = NULL;
01201 return -1;
01202 } else if ( (delta = config->play_warning - config->timelimit) > 0) {
01203 int w = config->warning_freq;
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217 if (w == 0) {
01218 config->play_warning = 0;
01219 } else {
01220 config->play_warning -= w * ( 1 + (delta-1)/w );
01221 if (config->play_warning < 1)
01222 config->play_warning = config->warning_freq = 0;
01223 }
01224 }
01225
01226 ast_channel_lock(chan);
01227
01228 var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLER");
01229
01230 play_to_caller = var ? ast_true(var) : 1;
01231
01232 var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLEE");
01233 play_to_callee = var ? ast_true(var) : 0;
01234
01235 if (!play_to_caller && !play_to_callee)
01236 play_to_caller = 1;
01237
01238 var = pbx_builtin_getvar_helper(chan, "LIMIT_WARNING_FILE");
01239 config->warning_sound = !ast_strlen_zero(var) ? ast_strdup(var) : ast_strdup("timeleft");
01240
01241
01242
01243
01244
01245
01246
01247 var = pbx_builtin_getvar_helper(chan, "LIMIT_TIMEOUT_FILE");
01248 config->end_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
01249
01250 var = pbx_builtin_getvar_helper(chan, "LIMIT_CONNECT_FILE");
01251 config->start_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
01252
01253 ast_channel_unlock(chan);
01254
01255
01256 calldurationlimit->tv_sec = 0;
01257 calldurationlimit->tv_usec = 0;
01258
01259
01260 if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
01261 calldurationlimit->tv_sec = config->timelimit / 1000;
01262 calldurationlimit->tv_usec = (config->timelimit % 1000) * 1000;
01263 ast_verb(3, "Setting call duration limit to %.3lf seconds.\n",
01264 calldurationlimit->tv_sec + calldurationlimit->tv_usec / 1000000.0);
01265 config->timelimit = play_to_caller = play_to_callee =
01266 config->play_warning = config->warning_freq = 0;
01267 } else {
01268 ast_verb(3, "Limit Data for this call:\n");
01269 ast_verb(4, "timelimit = %ld\n", config->timelimit);
01270 ast_verb(4, "play_warning = %ld\n", config->play_warning);
01271 ast_verb(4, "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
01272 ast_verb(4, "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
01273 ast_verb(4, "warning_freq = %ld\n", config->warning_freq);
01274 ast_verb(4, "start_sound = %s\n", S_OR(config->start_sound, ""));
01275 ast_verb(4, "warning_sound = %s\n", config->warning_sound);
01276 ast_verb(4, "end_sound = %s\n", S_OR(config->end_sound, ""));
01277 }
01278 if (play_to_caller)
01279 ast_set_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
01280 if (play_to_callee)
01281 ast_set_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
01282 return 0;
01283 }
01284
01285 static int do_privacy(struct ast_channel *chan, struct ast_channel *peer,
01286 struct ast_flags64 *opts, char **opt_args, struct privacy_args *pa)
01287 {
01288
01289 int res2;
01290 int loopcount = 0;
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300 if (ast_test_flag64(opts, OPT_MUSICBACK) && !ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
01301 char *original_moh = ast_strdupa(chan->musicclass);
01302 ast_indicate(chan, -1);
01303 ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
01304 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
01305 ast_string_field_set(chan, musicclass, original_moh);
01306 } else if (ast_test_flag64(opts, OPT_RINGBACK)) {
01307 ast_indicate(chan, AST_CONTROL_RINGING);
01308 pa->sentringing++;
01309 }
01310
01311
01312 res2 = ast_autoservice_start(chan);
01313
01314 for (loopcount = 0; loopcount < 3; loopcount++) {
01315 if (res2 && loopcount == 0)
01316 break;
01317 if (!res2)
01318 res2 = ast_play_and_wait(peer, "priv-callpending");
01319 if (!valid_priv_reply(opts, res2))
01320 res2 = 0;
01321
01322
01323
01324 if (!res2)
01325 res2 = ast_play_and_wait(peer, pa->privintro);
01326 if (!valid_priv_reply(opts, res2))
01327 res2 = 0;
01328
01329 if (!res2) {
01330
01331 if (ast_test_flag64(opts, OPT_PRIVACY))
01332 res2 = ast_play_and_wait(peer, "priv-callee-options");
01333 if (ast_test_flag64(opts, OPT_SCREENING))
01334 res2 = ast_play_and_wait(peer, "screen-callee-options");
01335 }
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352 if (valid_priv_reply(opts, res2))
01353 break;
01354
01355 res2 = ast_play_and_wait(peer, "vm-sorry");
01356 }
01357
01358 if (ast_test_flag64(opts, OPT_MUSICBACK)) {
01359 ast_moh_stop(chan);
01360 } else if (ast_test_flag64(opts, OPT_RINGBACK)) {
01361 ast_indicate(chan, -1);
01362 pa->sentringing = 0;
01363 }
01364 ast_autoservice_stop(chan);
01365 if (ast_test_flag64(opts, OPT_PRIVACY) && (res2 >= '1' && res2 <= '5')) {
01366
01367 static const char *_val[] = { "ALLOW", "DENY", "TORTURE", "KILL", "ALLOW" };
01368 static const int _flag[] = { AST_PRIVACY_ALLOW, AST_PRIVACY_DENY, AST_PRIVACY_TORTURE, AST_PRIVACY_KILL, AST_PRIVACY_ALLOW};
01369 int i = res2 - '1';
01370 ast_verb(3, "--Set privacy database entry %s/%s to %s\n",
01371 opt_args[OPT_ARG_PRIVACY], pa->privcid, _val[i]);
01372 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], pa->privcid, _flag[i]);
01373 }
01374 switch (res2) {
01375 case '1':
01376 break;
01377 case '2':
01378 ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status));
01379 break;
01380 case '3':
01381 ast_copy_string(pa->status, "TORTURE", sizeof(pa->status));
01382 break;
01383 case '4':
01384 ast_copy_string(pa->status, "DONTCALL", sizeof(pa->status));
01385 break;
01386 case '5':
01387
01388 if (ast_test_flag64(opts, OPT_PRIVACY))
01389 break;
01390
01391 default:
01392
01393
01394
01395
01396 ast_log(LOG_NOTICE, "privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
01397
01398
01399 break;
01400 }
01401
01402 if (res2 == '1') {
01403
01404
01405 if (strncmp(pa->privcid, "NOCALLERID", 10) == 0 || ast_test_flag64(opts, OPT_SCREEN_NOINTRO)) {
01406 ast_filedelete(pa->privintro, NULL);
01407 if (ast_fileexists(pa->privintro, NULL, NULL) > 0)
01408 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa->privintro);
01409 else
01410 ast_verb(3, "Successfully deleted %s intro file\n", pa->privintro);
01411 }
01412 return 0;
01413 } else {
01414 ast_hangup(peer);
01415 return -1;
01416 }
01417 }
01418
01419
01420 static int setup_privacy_args(struct privacy_args *pa,
01421 struct ast_flags64 *opts, char *opt_args[], struct ast_channel *chan)
01422 {
01423 char callerid[60];
01424 int res;
01425 char *l;
01426 int silencethreshold;
01427
01428 if (!ast_strlen_zero(chan->cid.cid_num)) {
01429 l = ast_strdupa(chan->cid.cid_num);
01430 ast_shrink_phone_number(l);
01431 if (ast_test_flag64(opts, OPT_PRIVACY) ) {
01432 ast_verb(3, "Privacy DB is '%s', clid is '%s'\n", opt_args[OPT_ARG_PRIVACY], l);
01433 pa->privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l);
01434 } else {
01435 ast_verb(3, "Privacy Screening, clid is '%s'\n", l);
01436 pa->privdb_val = AST_PRIVACY_UNKNOWN;
01437 }
01438 } else {
01439 char *tnam, *tn2;
01440
01441 tnam = ast_strdupa(chan->name);
01442
01443 for (tn2 = tnam; *tn2; tn2++) {
01444 if (*tn2 == '/')
01445 *tn2 = '=';
01446 }
01447 ast_verb(3, "Privacy-- callerid is empty\n");
01448
01449 snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
01450 l = callerid;
01451 pa->privdb_val = AST_PRIVACY_UNKNOWN;
01452 }
01453
01454 ast_copy_string(pa->privcid, l, sizeof(pa->privcid));
01455
01456 if (strncmp(pa->privcid, "NOCALLERID", 10) != 0 && ast_test_flag64(opts, OPT_SCREEN_NOCLID)) {
01457
01458 ast_verb(3, "CallerID set (%s); N option set; Screening should be off\n", pa->privcid);
01459 pa->privdb_val = AST_PRIVACY_ALLOW;
01460 } else if (ast_test_flag64(opts, OPT_SCREEN_NOCLID) && strncmp(pa->privcid, "NOCALLERID", 10) == 0) {
01461 ast_verb(3, "CallerID blank; N option set; Screening should happen; dbval is %d\n", pa->privdb_val);
01462 }
01463
01464 if (pa->privdb_val == AST_PRIVACY_DENY) {
01465 ast_verb(3, "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
01466 ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status));
01467 return 0;
01468 } else if (pa->privdb_val == AST_PRIVACY_KILL) {
01469 ast_copy_string(pa->status, "DONTCALL", sizeof(pa->status));
01470 return 0;
01471 } else if (pa->privdb_val == AST_PRIVACY_TORTURE) {
01472 ast_copy_string(pa->status, "TORTURE", sizeof(pa->status));
01473 return 0;
01474 } else if (pa->privdb_val == AST_PRIVACY_UNKNOWN) {
01475
01476
01477
01478
01479
01480 snprintf(pa->privintro, sizeof(pa->privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR);
01481 if ((res = ast_mkdir(pa->privintro, 0755))) {
01482 ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(res));
01483 return -1;
01484 }
01485
01486 snprintf(pa->privintro, sizeof(pa->privintro), "priv-callerintros/%s", pa->privcid);
01487 if (ast_fileexists(pa->privintro, NULL, NULL ) > 0 && strncmp(pa->privcid, "NOCALLERID", 10) != 0) {
01488
01489
01490
01491 } else {
01492 int duration;
01493
01494
01495
01496
01497
01498
01499
01500 silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
01501 ast_answer(chan);
01502 res = ast_play_and_record(chan, "priv-recordintro", pa->privintro, 4, "sln", &duration, silencethreshold, 2000, 0);
01503
01504
01505 if (res == -1) {
01506
01507 ast_filedelete(pa->privintro, NULL);
01508 if (ast_fileexists(pa->privintro, NULL, NULL) > 0)
01509 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa->privintro);
01510 else
01511 ast_verb(3, "Successfully deleted %s intro file\n", pa->privintro);
01512 return -1;
01513 }
01514 if (!ast_streamfile(chan, "vm-dialout", chan->language) )
01515 ast_waitstream(chan, "");
01516 }
01517 }
01518 return 1;
01519 }
01520
01521 static void end_bridge_callback(void *data)
01522 {
01523 char buf[80];
01524 time_t end;
01525 struct ast_channel *chan = data;
01526
01527 if (!chan->cdr) {
01528 return;
01529 }
01530
01531 time(&end);
01532
01533 ast_channel_lock(chan);
01534 if (chan->cdr->answer.tv_sec) {
01535 snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->answer.tv_sec);
01536 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf);
01537 }
01538
01539 if (chan->cdr->start.tv_sec) {
01540 snprintf(buf, sizeof(buf), "%ld", (long) end - chan->cdr->start.tv_sec);
01541 pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf);
01542 }
01543 ast_channel_unlock(chan);
01544 }
01545
01546 static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator) {
01547 bconfig->end_bridge_callback_data = originator;
01548 }
01549
01550 static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags64 *peerflags, int *continue_exec)
01551 {
01552 int res = -1;
01553 char *rest, *cur;
01554 struct chanlist *outgoing = NULL;
01555 struct ast_channel *peer;
01556 int to;
01557 struct cause_args num = { chan, 0, 0, 0 };
01558 int cause;
01559 char numsubst[256];
01560 char cidname[AST_MAX_EXTENSION] = "";
01561
01562 struct ast_bridge_config config = { { 0, } };
01563 struct timeval calldurationlimit = { 0, };
01564 char *dtmfcalled = NULL, *dtmfcalling = NULL;
01565 struct privacy_args pa = {
01566 .sentringing = 0,
01567 .privdb_val = 0,
01568 .status = "INVALIDARGS",
01569 };
01570 int sentringing = 0, moh = 0;
01571 const char *outbound_group = NULL;
01572 int result = 0;
01573 char *parse;
01574 int opermode = 0;
01575 int delprivintro = 0;
01576 AST_DECLARE_APP_ARGS(args,
01577 AST_APP_ARG(peers);
01578 AST_APP_ARG(timeout);
01579 AST_APP_ARG(options);
01580 AST_APP_ARG(url);
01581 );
01582 struct ast_flags64 opts = { 0, };
01583 char *opt_args[OPT_ARG_ARRAY_SIZE];
01584 struct ast_datastore *datastore = NULL;
01585 int fulldial = 0, num_dialed = 0;
01586
01587
01588 pbx_builtin_setvar_helper(chan, "DIALSTATUS", "");
01589 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", "");
01590 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", "");
01591 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", "");
01592 pbx_builtin_setvar_helper(chan, "DIALEDTIME", "");
01593
01594 if (ast_strlen_zero(data)) {
01595 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
01596 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01597 return -1;
01598 }
01599
01600 parse = ast_strdupa(data);
01601
01602 AST_STANDARD_APP_ARGS(args, parse);
01603
01604 if (!ast_strlen_zero(args.options) &&
01605 ast_app_parse_options64(dial_exec_options, &opts, opt_args, args.options)) {
01606 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01607 goto done;
01608 }
01609
01610 if (ast_strlen_zero(args.peers)) {
01611 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
01612 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01613 goto done;
01614 }
01615
01616
01617 if (ast_test_flag64(&opts, OPT_SCREEN_NOINTRO) && !ast_strlen_zero(opt_args[OPT_ARG_SCREEN_NOINTRO])) {
01618 delprivintro = atoi(opt_args[OPT_ARG_SCREEN_NOINTRO]);
01619
01620 if (delprivintro < 0 || delprivintro > 1) {
01621 ast_log(LOG_WARNING, "Unknown argument %d specified to n option, ignoring\n", delprivintro);
01622 delprivintro = 0;
01623 }
01624 }
01625
01626 if (ast_test_flag64(&opts, OPT_OPERMODE)) {
01627 opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]);
01628 ast_verb(3, "Setting operator services mode to %d.\n", opermode);
01629 }
01630
01631 if (ast_test_flag64(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
01632 calldurationlimit.tv_sec = atoi(opt_args[OPT_ARG_DURATION_STOP]);
01633 if (!calldurationlimit.tv_sec) {
01634 ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]);
01635 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01636 goto done;
01637 }
01638 ast_verb(3, "Setting call duration limit to %.3lf seconds.\n", calldurationlimit.tv_sec + calldurationlimit.tv_usec / 1000000.0);
01639 }
01640
01641 if (ast_test_flag64(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
01642 dtmfcalling = opt_args[OPT_ARG_SENDDTMF];
01643 dtmfcalled = strsep(&dtmfcalling, ":");
01644 }
01645
01646 if (ast_test_flag64(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
01647 if (do_timelimit(chan, &config, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit))
01648 goto done;
01649 }
01650
01651 if (ast_test_flag64(&opts, OPT_RESETCDR) && chan->cdr)
01652 ast_cdr_reset(chan->cdr, NULL);
01653 if (ast_test_flag64(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY]))
01654 opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten);
01655
01656 if (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) {
01657 res = setup_privacy_args(&pa, &opts, opt_args, chan);
01658 if (res <= 0)
01659 goto out;
01660 res = -1;
01661 }
01662
01663 if (ast_test_flag64(&opts, OPT_DTMF_EXIT) || ast_test_flag64(&opts, OPT_CALLER_HANGUP)) {
01664 __ast_answer(chan, 0, 0);
01665 }
01666
01667 if (continue_exec)
01668 *continue_exec = 0;
01669
01670
01671
01672 ast_channel_lock(chan);
01673 if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP_ONCE"))) {
01674 outbound_group = ast_strdupa(outbound_group);
01675 pbx_builtin_setvar_helper(chan, "OUTBOUND_GROUP_ONCE", NULL);
01676 } else if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP"))) {
01677 outbound_group = ast_strdupa(outbound_group);
01678 }
01679 ast_channel_unlock(chan);
01680 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);
01681
01682
01683 rest = args.peers;
01684 while ((cur = strsep(&rest, "&")) ) {
01685 struct chanlist *tmp;
01686 struct ast_channel *tc;
01687
01688 char *number = cur;
01689 char *interface = ast_strdupa(number);
01690 char *tech = strsep(&number, "/");
01691
01692 struct ast_dialed_interface *di;
01693 AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
01694 num_dialed++;
01695 if (ast_strlen_zero(number)) {
01696 ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n");
01697 goto out;
01698 }
01699 if (!(tmp = ast_calloc(1, sizeof(*tmp))))
01700 goto out;
01701 if (opts.flags) {
01702 ast_copy_flags64(tmp, &opts,
01703 OPT_CANCEL_ELSEWHERE |
01704 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
01705 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
01706 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
01707 OPT_CALLEE_PARK | OPT_CALLER_PARK |
01708 OPT_CALLEE_MIXMONITOR | OPT_CALLER_MIXMONITOR |
01709 OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID);
01710 ast_set2_flag64(tmp, args.url, DIAL_NOFORWARDHTML);
01711 }
01712 ast_copy_string(numsubst, number, sizeof(numsubst));
01713
01714
01715 ast_channel_lock(chan);
01716 datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL);
01717 ast_channel_unlock(chan);
01718
01719 if (datastore)
01720 dialed_interfaces = datastore->data;
01721 else {
01722 if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) {
01723 ast_log(LOG_WARNING, "Unable to create channel datastore for dialed interfaces. Aborting!\n");
01724 ast_free(tmp);
01725 goto out;
01726 }
01727
01728 datastore->inheritance = DATASTORE_INHERIT_FOREVER;
01729
01730 if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {
01731 ast_datastore_free(datastore);
01732 ast_free(tmp);
01733 goto out;
01734 }
01735
01736 datastore->data = dialed_interfaces;
01737 AST_LIST_HEAD_INIT(dialed_interfaces);
01738
01739 ast_channel_lock(chan);
01740 ast_channel_datastore_add(chan, datastore);
01741 ast_channel_unlock(chan);
01742 }
01743
01744 AST_LIST_LOCK(dialed_interfaces);
01745 AST_LIST_TRAVERSE(dialed_interfaces, di, list) {
01746 if (!strcasecmp(di->interface, interface)) {
01747 ast_log(LOG_WARNING, "Skipping dialing interface '%s' again since it has already been dialed\n",
01748 di->interface);
01749 break;
01750 }
01751 }
01752 AST_LIST_UNLOCK(dialed_interfaces);
01753
01754 if (di) {
01755 fulldial++;
01756 ast_free(tmp);
01757 continue;
01758 }
01759
01760
01761
01762
01763
01764 if (strcasecmp(tech, "Local")) {
01765 if (!(di = ast_calloc(1, sizeof(*di) + strlen(interface)))) {
01766 AST_LIST_UNLOCK(dialed_interfaces);
01767 ast_free(tmp);
01768 goto out;
01769 }
01770 strcpy(di->interface, interface);
01771
01772 AST_LIST_LOCK(dialed_interfaces);
01773 AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
01774 AST_LIST_UNLOCK(dialed_interfaces);
01775 }
01776
01777 tc = ast_request(tech, chan->nativeformats, numsubst, &cause);
01778 if (!tc) {
01779
01780 ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n",
01781 tech, cause, ast_cause2str(cause));
01782 handle_cause(cause, &num);
01783 if (!rest)
01784 chan->hangupcause = cause;
01785 ast_free(tmp);
01786 continue;
01787 }
01788 pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", numsubst);
01789
01790
01791 if (CAN_EARLY_BRIDGE(peerflags, chan, tc)) {
01792 ast_rtp_make_compatible(tc, chan, !outgoing && !rest);
01793 }
01794
01795
01796 ast_channel_inherit_variables(chan, tc);
01797 ast_channel_datastore_inherit(chan, tc);
01798
01799 tc->appl = "AppDial";
01800 tc->data = "(Outgoing Line)";
01801 memset(&tc->whentohangup, 0, sizeof(tc->whentohangup));
01802
01803 S_REPLACE(tc->cid.cid_num, ast_strdup(chan->cid.cid_num));
01804 S_REPLACE(tc->cid.cid_name, ast_strdup(chan->cid.cid_name));
01805 S_REPLACE(tc->cid.cid_ani, ast_strdup(chan->cid.cid_ani));
01806 S_REPLACE(tc->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis));
01807
01808 ast_string_field_set(tc, accountcode, chan->accountcode);
01809 tc->cdrflags = chan->cdrflags;
01810 if (ast_strlen_zero(tc->musicclass))
01811 ast_string_field_set(tc, musicclass, chan->musicclass);
01812
01813 tc->cid.cid_pres = chan->cid.cid_pres;
01814 tc->cid.cid_ton = chan->cid.cid_ton;
01815 tc->cid.cid_tns = chan->cid.cid_tns;
01816 tc->cid.cid_ani2 = chan->cid.cid_ani2;
01817 tc->adsicpe = chan->adsicpe;
01818 tc->transfercapability = chan->transfercapability;
01819
01820
01821 if (outbound_group)
01822 ast_app_group_set_channel(tc, outbound_group);
01823
01824 if (ast_test_flag(chan, AST_FLAG_ANSWERED_ELSEWHERE))
01825 ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE);
01826
01827
01828 if (ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE))
01829 ast_set_flag(tc, AST_FLAG_ANSWERED_ELSEWHERE);
01830
01831
01832
01833 ast_string_field_set(tc, dialcontext, ast_strlen_zero(chan->macrocontext) ? chan->context : chan->macrocontext);
01834 if (!ast_strlen_zero(chan->macroexten))
01835 ast_copy_string(tc->exten, chan->macroexten, sizeof(tc->exten));
01836 else
01837 ast_copy_string(tc->exten, chan->exten, sizeof(tc->exten));
01838
01839 res = ast_call(tc, numsubst, 0);
01840
01841
01842 if (chan->cdr)
01843 ast_cdr_setdestchan(chan->cdr, tc->name);
01844
01845
01846 if (res) {
01847
01848 ast_debug(1, "ast call on peer returned %d\n", res);
01849 ast_verb(3, "Couldn't call %s\n", numsubst);
01850 if (tc->hangupcause) {
01851 chan->hangupcause = tc->hangupcause;
01852 }
01853 ast_hangup(tc);
01854 tc = NULL;
01855 ast_free(tmp);
01856 continue;
01857 } else {
01858 senddialevent(chan, tc, numsubst);
01859 ast_verb(3, "Called %s\n", numsubst);
01860 if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID))
01861 ast_set_callerid(tc, S_OR(chan->macroexten, chan->exten), get_cid_name(cidname, sizeof(cidname), chan), NULL);
01862 }
01863
01864
01865
01866 ast_set_flag64(tmp, DIAL_STILLGOING);
01867 tmp->chan = tc;
01868 tmp->next = outgoing;
01869 outgoing = tmp;
01870
01871 if (outgoing->chan->_state == AST_STATE_UP)
01872 break;
01873 }
01874
01875 if (ast_strlen_zero(args.timeout)) {
01876 to = -1;
01877 } else {
01878 to = atoi(args.timeout);
01879 if (to > 0)
01880 to *= 1000;
01881 else {
01882 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'. Setting timeout to infinite\n", args.timeout);
01883 to = -1;
01884 }
01885 }
01886
01887 if (!outgoing) {
01888 strcpy(pa.status, "CHANUNAVAIL");
01889 if (fulldial == num_dialed) {
01890 res = -1;
01891 goto out;
01892 }
01893 } else {
01894
01895 strcpy(pa.status, "NOANSWER");
01896 if (ast_test_flag64(outgoing, OPT_MUSICBACK)) {
01897 moh = 1;
01898 if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
01899 char *original_moh = ast_strdupa(chan->musicclass);
01900 ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
01901 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
01902 ast_string_field_set(chan, musicclass, original_moh);
01903 } else {
01904 ast_moh_start(chan, NULL, NULL);
01905 }
01906 ast_indicate(chan, AST_CONTROL_PROGRESS);
01907 } else if (ast_test_flag64(outgoing, OPT_RINGBACK)) {
01908 ast_indicate(chan, AST_CONTROL_RINGING);
01909 sentringing++;
01910 }
01911 }
01912
01913 peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result);
01914
01915
01916
01917
01918
01919
01920
01921 ast_channel_lock(chan);
01922 if (!ast_channel_datastore_remove(chan, datastore)) {
01923 ast_datastore_free(datastore);
01924 }
01925 ast_channel_unlock(chan);
01926 if (!peer) {
01927 if (result) {
01928 res = result;
01929 } else if (to) {
01930 res = -1;
01931 } else {
01932 res = 0;
01933 }
01934
01935
01936
01937 if (chan->hangupcause == AST_CAUSE_INVALID_NUMBER_FORMAT) {
01938 res = AST_PBX_INCOMPLETE;
01939 }
01940
01941
01942 } else {
01943 const char *number;
01944
01945 strcpy(pa.status, "ANSWER");
01946 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
01947
01948
01949
01950 hanguptree(outgoing, peer, 1);
01951 outgoing = NULL;
01952
01953 if (chan->cdr)
01954 ast_cdr_setdestchan(chan->cdr, peer->name);
01955 if (peer->name)
01956 pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
01957
01958 ast_channel_lock(peer);
01959 number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
01960 if (!number)
01961 number = numsubst;
01962 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
01963 ast_channel_unlock(peer);
01964
01965 if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
01966 ast_debug(1, "app_dial: sendurl=%s.\n", args.url);
01967 ast_channel_sendurl( peer, args.url );
01968 }
01969 if ( (ast_test_flag64(&opts, OPT_PRIVACY) || ast_test_flag64(&opts, OPT_SCREENING)) && pa.privdb_val == AST_PRIVACY_UNKNOWN) {
01970 if (do_privacy(chan, peer, &opts, opt_args, &pa)) {
01971 res = 0;
01972 goto out;
01973 }
01974 }
01975 if (!ast_test_flag64(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) {
01976 res = 0;
01977 } else {
01978 int digit = 0;
01979 struct ast_channel *chans[2];
01980 struct ast_channel *active_chan;
01981
01982 chans[0] = chan;
01983 chans[1] = peer;
01984
01985
01986
01987
01988 res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language);
01989 if (res) {
01990 res = 0;
01991 ast_log(LOG_ERROR, "error streaming file '%s' to callee\n", opt_args[OPT_ARG_ANNOUNCE]);
01992 }
01993
01994 ast_set_flag(peer, AST_FLAG_END_DTMF_ONLY);
01995 while (peer->stream) {
01996 int ms;
01997
01998 ms = ast_sched_wait(peer->sched);
01999
02000 if (ms < 0 && !peer->timingfunc) {
02001 ast_stopstream(peer);
02002 break;
02003 }
02004 if (ms < 0)
02005 ms = 1000;
02006
02007 active_chan = ast_waitfor_n(chans, 2, &ms);
02008 if (active_chan) {
02009 struct ast_frame *fr = ast_read(active_chan);
02010 if (!fr) {
02011 ast_hangup(peer);
02012 res = -1;
02013 goto done;
02014 }
02015 switch(fr->frametype) {
02016 case AST_FRAME_DTMF_END:
02017 digit = fr->subclass;
02018 if (active_chan == peer && strchr(AST_DIGIT_ANY, res)) {
02019 ast_stopstream(peer);
02020 res = ast_senddigit(chan, digit, 0);
02021 }
02022 break;
02023 case AST_FRAME_CONTROL:
02024 switch (fr->subclass) {
02025 case AST_CONTROL_HANGUP:
02026 ast_frfree(fr);
02027 ast_hangup(peer);
02028 res = -1;
02029 goto done;
02030 default:
02031 break;
02032 }
02033 break;
02034 default:
02035
02036 break;
02037 }
02038 ast_frfree(fr);
02039 }
02040 ast_sched_runq(peer->sched);
02041 }
02042 ast_clear_flag(peer, AST_FLAG_END_DTMF_ONLY);
02043 }
02044
02045 if (chan && peer && ast_test_flag64(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) {
02046
02047
02048 ast_clear_flag(chan->cdr, AST_CDR_FLAG_DIALED);
02049 ast_clear_flag(peer->cdr, AST_CDR_FLAG_DIALED);
02050
02051 replace_macro_delimiter(opt_args[OPT_ARG_GOTO]);
02052 ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
02053
02054 ast_copy_string(peer->context, chan->context, sizeof(peer->context));
02055 ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten));
02056 peer->priority = chan->priority + 2;
02057 ast_pbx_start(peer);
02058 hanguptree(outgoing, NULL, ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE) ? 1 : 0);
02059 if (continue_exec)
02060 *continue_exec = 1;
02061 res = 0;
02062 goto done;
02063 }
02064
02065 if (ast_test_flag64(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) {
02066 struct ast_app *theapp;
02067 const char *macro_result;
02068
02069 res = ast_autoservice_start(chan);
02070 if (res) {
02071 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
02072 res = -1;
02073 }
02074
02075 theapp = pbx_findapp("Macro");
02076
02077 if (theapp && !res) {
02078
02079 ast_copy_string(peer->context, chan->context, sizeof(peer->context));
02080 ast_copy_string(peer->exten, chan->exten, sizeof(peer->exten));
02081
02082 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]);
02083 res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]);
02084 ast_debug(1, "Macro exited with status %d\n", res);
02085 res = 0;
02086 } else {
02087 ast_log(LOG_ERROR, "Could not find application Macro\n");
02088 res = -1;
02089 }
02090
02091 if (ast_autoservice_stop(chan) < 0) {
02092 res = -1;
02093 }
02094
02095 ast_channel_lock(peer);
02096
02097 if (!res && (macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
02098 char *macro_transfer_dest;
02099
02100 if (!strcasecmp(macro_result, "BUSY")) {
02101 ast_copy_string(pa.status, macro_result, sizeof(pa.status));
02102 ast_set_flag64(peerflags, OPT_GO_ON);
02103 res = -1;
02104 } else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
02105 ast_copy_string(pa.status, macro_result, sizeof(pa.status));
02106 ast_set_flag64(peerflags, OPT_GO_ON);
02107 res = -1;
02108 } else if (!strcasecmp(macro_result, "CONTINUE")) {
02109
02110
02111
02112
02113 ast_set_flag64(peerflags, OPT_GO_ON);
02114 res = -1;
02115 } else if (!strcasecmp(macro_result, "ABORT")) {
02116
02117 res = -1;
02118 } else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
02119 res = -1;
02120
02121 if (strchr(macro_transfer_dest, '^')) {
02122 replace_macro_delimiter(macro_transfer_dest);
02123 if (!ast_parseable_goto(chan, macro_transfer_dest))
02124 ast_set_flag64(peerflags, OPT_GO_ON);
02125 }
02126 }
02127 }
02128
02129 ast_channel_unlock(peer);
02130 }
02131
02132 if (ast_test_flag64(&opts, OPT_CALLEE_GOSUB) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GOSUB])) {
02133 struct ast_app *theapp;
02134 const char *gosub_result;
02135 char *gosub_args, *gosub_argstart;
02136 int res9 = -1;
02137
02138 res9 = ast_autoservice_start(chan);
02139 if (res9) {
02140 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
02141 res9 = -1;
02142 }
02143
02144 theapp = pbx_findapp("Gosub");
02145
02146 if (theapp && !res9) {
02147 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GOSUB]);
02148
02149
02150 ast_copy_string(peer->context, "app_dial_gosub_virtual_context", sizeof(peer->context));
02151 ast_copy_string(peer->exten, "s", sizeof(peer->exten));
02152 peer->priority = 0;
02153
02154 gosub_argstart = strchr(opt_args[OPT_ARG_CALLEE_GOSUB], ',');
02155 if (gosub_argstart) {
02156 *gosub_argstart = 0;
02157 if (asprintf(&gosub_args, "%s,s,1(%s)", opt_args[OPT_ARG_CALLEE_GOSUB], gosub_argstart + 1) < 0) {
02158 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
02159 gosub_args = NULL;
02160 }
02161 *gosub_argstart = ',';
02162 } else {
02163 if (asprintf(&gosub_args, "%s,s,1", opt_args[OPT_ARG_CALLEE_GOSUB]) < 0) {
02164 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
02165 gosub_args = NULL;
02166 }
02167 }
02168
02169 if (gosub_args) {
02170 res9 = pbx_exec(peer, theapp, gosub_args);
02171 if (!res9) {
02172 struct ast_pbx_args args;
02173
02174 memset(&args, 0, sizeof(args));
02175 args.no_hangup_chan = 1;
02176 ast_pbx_run_args(peer, &args);
02177 }
02178 ast_free(gosub_args);
02179 ast_debug(1, "Gosub exited with status %d\n", res9);
02180 } else {
02181 ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n");
02182 }
02183
02184 } else if (!res9) {
02185 ast_log(LOG_ERROR, "Could not find application Gosub\n");
02186 res9 = -1;
02187 }
02188
02189 if (ast_autoservice_stop(chan) < 0) {
02190 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
02191 res9 = -1;
02192 }
02193
02194 ast_channel_lock(peer);
02195
02196 if (!res9 && (gosub_result = pbx_builtin_getvar_helper(peer, "GOSUB_RESULT"))) {
02197 char *gosub_transfer_dest;
02198
02199 if (!strcasecmp(gosub_result, "BUSY")) {
02200 ast_copy_string(pa.status, gosub_result, sizeof(pa.status));
02201 ast_set_flag64(peerflags, OPT_GO_ON);
02202 res = -1;
02203 } else if (!strcasecmp(gosub_result, "CONGESTION") || !strcasecmp(gosub_result, "CHANUNAVAIL")) {
02204 ast_copy_string(pa.status, gosub_result, sizeof(pa.status));
02205 ast_set_flag64(peerflags, OPT_GO_ON);
02206 res = -1;
02207 } else if (!strcasecmp(gosub_result, "CONTINUE")) {
02208
02209
02210
02211
02212 ast_set_flag64(peerflags, OPT_GO_ON);
02213 res = -1;
02214 } else if (!strcasecmp(gosub_result, "ABORT")) {
02215
02216 res = -1;
02217 } else if (!strncasecmp(gosub_result, "GOTO:", 5) && (gosub_transfer_dest = ast_strdupa(gosub_result + 5))) {
02218 res = -1;
02219
02220 if (strchr(gosub_transfer_dest, '^')) {
02221 replace_macro_delimiter(gosub_transfer_dest);
02222 if (!ast_parseable_goto(chan, gosub_transfer_dest))
02223 ast_set_flag64(peerflags, OPT_GO_ON);
02224 }
02225 }
02226 }
02227
02228 ast_channel_unlock(peer);
02229 }
02230
02231 if (!res) {
02232 if (!ast_tvzero(calldurationlimit)) {
02233 struct timeval whentohangup = calldurationlimit;
02234 peer->whentohangup = ast_tvadd(ast_tvnow(), whentohangup);
02235 }
02236 if (!ast_strlen_zero(dtmfcalled)) {
02237 ast_verb(3, "Sending DTMF '%s' to the called party.\n", dtmfcalled);
02238 res = ast_dtmf_stream(peer, chan, dtmfcalled, 250, 0);
02239 }
02240 if (!ast_strlen_zero(dtmfcalling)) {
02241 ast_verb(3, "Sending DTMF '%s' to the calling party.\n", dtmfcalling);
02242 res = ast_dtmf_stream(chan, peer, dtmfcalling, 250, 0);
02243 }
02244 }
02245
02246 if (res) {
02247 res = -1;
02248 } else {
02249 if (ast_test_flag64(peerflags, OPT_CALLEE_TRANSFER))
02250 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
02251 if (ast_test_flag64(peerflags, OPT_CALLER_TRANSFER))
02252 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
02253 if (ast_test_flag64(peerflags, OPT_CALLEE_HANGUP))
02254 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
02255 if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP))
02256 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
02257 if (ast_test_flag64(peerflags, OPT_CALLEE_MONITOR))
02258 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
02259 if (ast_test_flag64(peerflags, OPT_CALLER_MONITOR))
02260 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
02261 if (ast_test_flag64(peerflags, OPT_CALLEE_PARK))
02262 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
02263 if (ast_test_flag64(peerflags, OPT_CALLER_PARK))
02264 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
02265 if (ast_test_flag64(peerflags, OPT_CALLEE_MIXMONITOR))
02266 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMIXMON);
02267 if (ast_test_flag64(peerflags, OPT_CALLER_MIXMONITOR))
02268 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMIXMON);
02269 if (ast_test_flag64(peerflags, OPT_GO_ON))
02270 ast_set_flag(&(config.features_caller), AST_FEATURE_NO_H_EXTEN);
02271
02272 config.end_bridge_callback = end_bridge_callback;
02273 config.end_bridge_callback_data = chan;
02274 config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
02275
02276 if (moh) {
02277 moh = 0;
02278 ast_moh_stop(chan);
02279 } else if (sentringing) {
02280 sentringing = 0;
02281 ast_indicate(chan, -1);
02282 }
02283
02284 ast_deactivate_generator(chan);
02285 chan->visible_indication = 0;
02286
02287 res = ast_channel_make_compatible(chan, peer);
02288 if (res < 0) {
02289 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
02290 ast_hangup(peer);
02291 res = -1;
02292 goto done;
02293 }
02294 if (opermode) {
02295 struct oprmode oprmode;
02296
02297 oprmode.peer = peer;
02298 oprmode.mode = opermode;
02299
02300 ast_channel_setoption(chan, AST_OPTION_OPRMODE, &oprmode, sizeof(oprmode), 0);
02301 }
02302 res = ast_bridge_call(chan, peer, &config);
02303 }
02304
02305 strcpy(peer->context, chan->context);
02306
02307 if (ast_test_flag64(&opts, OPT_PEER_H) && ast_exists_extension(peer, peer->context, "h", 1, peer->cid.cid_num)) {
02308 int autoloopflag;
02309 int found;
02310 int res9;
02311
02312 strcpy(peer->exten, "h");
02313 peer->priority = 1;
02314 autoloopflag = ast_test_flag(peer, AST_FLAG_IN_AUTOLOOP);
02315 ast_set_flag(peer, AST_FLAG_IN_AUTOLOOP);
02316
02317 while ((res9 = ast_spawn_extension(peer, peer->context, peer->exten, peer->priority, peer->cid.cid_num, &found, 1)) == 0)
02318 peer->priority++;
02319
02320 if (found && res9) {
02321
02322 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
02323 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
02324 }
02325 ast_set2_flag(peer, autoloopflag, AST_FLAG_IN_AUTOLOOP);
02326 }
02327 if (!ast_check_hangup(peer) && ast_test_flag64(&opts, OPT_CALLEE_GO_ON) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) {
02328 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
02329 ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]);
02330 ast_pbx_start(peer);
02331 } else {
02332 if (!ast_check_hangup(chan))
02333 chan->hangupcause = peer->hangupcause;
02334 ast_hangup(peer);
02335 }
02336 }
02337 out:
02338 if (moh) {
02339 moh = 0;
02340 ast_moh_stop(chan);
02341 } else if (sentringing) {
02342 sentringing = 0;
02343 ast_indicate(chan, -1);
02344 }
02345
02346 if (delprivintro && ast_fileexists(pa.privintro, NULL, NULL) > 0) {
02347 ast_filedelete(pa.privintro, NULL);
02348 if (ast_fileexists(pa.privintro, NULL, NULL) > 0) {
02349 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa.privintro);
02350 } else {
02351 ast_verb(3, "Successfully deleted %s intro file\n", pa.privintro);
02352 }
02353 }
02354
02355 ast_channel_early_bridge(chan, NULL);
02356 hanguptree(outgoing, NULL, 0);
02357 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
02358 senddialendevent(chan, pa.status);
02359 ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);
02360
02361 if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_INCOMPLETE)) {
02362 if (!ast_tvzero(calldurationlimit))
02363 memset(&chan->whentohangup, 0, sizeof(chan->whentohangup));
02364 res = 0;
02365 }
02366
02367 done:
02368 if (config.warning_sound) {
02369 ast_free((char *)config.warning_sound);
02370 }
02371 if (config.end_sound) {
02372 ast_free((char *)config.end_sound);
02373 }
02374 if (config.start_sound) {
02375 ast_free((char *)config.start_sound);
02376 }
02377 return res;
02378 }
02379
02380 static int dial_exec(struct ast_channel *chan, void *data)
02381 {
02382 struct ast_flags64 peerflags;
02383
02384 memset(&peerflags, 0, sizeof(peerflags));
02385
02386 return dial_exec_full(chan, data, &peerflags, NULL);
02387 }
02388
02389 static int retrydial_exec(struct ast_channel *chan, void *data)
02390 {
02391 char *parse;
02392 const char *context = NULL;
02393 int sleepms = 0, loops = 0, res = -1;
02394 struct ast_flags64 peerflags = { 0, };
02395 AST_DECLARE_APP_ARGS(args,
02396 AST_APP_ARG(announce);
02397 AST_APP_ARG(sleep);
02398 AST_APP_ARG(retries);
02399 AST_APP_ARG(dialdata);
02400 );
02401
02402 if (ast_strlen_zero(data)) {
02403 ast_log(LOG_WARNING, "RetryDial requires an argument!\n");
02404 return -1;
02405 }
02406
02407 parse = ast_strdupa(data);
02408 AST_STANDARD_APP_ARGS(args, parse);
02409
02410 if (!ast_strlen_zero(args.sleep) && (sleepms = atoi(args.sleep)))
02411 sleepms *= 1000;
02412
02413 if (!ast_strlen_zero(args.retries)) {
02414 loops = atoi(args.retries);
02415 }
02416
02417 if (!args.dialdata) {
02418 ast_log(LOG_ERROR, "%s requires a 4th argument (dialdata)\n", rapp);
02419 goto done;
02420 }
02421
02422 if (sleepms < 1000)
02423 sleepms = 10000;
02424
02425 if (!loops)
02426 loops = -1;
02427
02428 ast_channel_lock(chan);
02429 context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT");
02430 context = !ast_strlen_zero(context) ? ast_strdupa(context) : NULL;
02431 ast_channel_unlock(chan);
02432
02433 res = 0;
02434 while (loops) {
02435 int continue_exec;
02436
02437 chan->data = "Retrying";
02438 if (ast_test_flag(chan, AST_FLAG_MOH))
02439 ast_moh_stop(chan);
02440
02441 res = dial_exec_full(chan, args.dialdata, &peerflags, &continue_exec);
02442 if (continue_exec)
02443 break;
02444
02445 if (res == 0) {
02446 if (ast_test_flag64(&peerflags, OPT_DTMF_EXIT)) {
02447 if (!ast_strlen_zero(args.announce)) {
02448 if (ast_fileexists(args.announce, NULL, chan->language) > 0) {
02449 if (!(res = ast_streamfile(chan, args.announce, chan->language)))
02450 ast_waitstream(chan, AST_DIGIT_ANY);
02451 } else
02452 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce);
02453 }
02454 if (!res && sleepms) {
02455 if (!ast_test_flag(chan, AST_FLAG_MOH))
02456 ast_moh_start(chan, NULL, NULL);
02457 res = ast_waitfordigit(chan, sleepms);
02458 }
02459 } else {
02460 if (!ast_strlen_zero(args.announce)) {
02461 if (ast_fileexists(args.announce, NULL, chan->language) > 0) {
02462 if (!(res = ast_streamfile(chan, args.announce, chan->language)))
02463 res = ast_waitstream(chan, "");
02464 } else
02465 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce);
02466 }
02467 if (sleepms) {
02468 if (!ast_test_flag(chan, AST_FLAG_MOH))
02469 ast_moh_start(chan, NULL, NULL);
02470 if (!res)
02471 res = ast_waitfordigit(chan, sleepms);
02472 }
02473 }
02474 }
02475
02476 if (res < 0 || res == AST_PBX_INCOMPLETE) {
02477 break;
02478 } else if (res > 0) {
02479 if (onedigit_goto(chan, context, (char) res, 1)) {
02480 res = 0;
02481 break;
02482 }
02483 }
02484 loops--;
02485 }
02486 if (loops == 0)
02487 res = 0;
02488 else if (res == 1)
02489 res = 0;
02490
02491 if (ast_test_flag(chan, AST_FLAG_MOH))
02492 ast_moh_stop(chan);
02493 done:
02494 return res;
02495 }
02496
02497 static int unload_module(void)
02498 {
02499 int res;
02500 struct ast_context *con;
02501
02502 res = ast_unregister_application(app);
02503 res |= ast_unregister_application(rapp);
02504
02505 if ((con = ast_context_find("app_dial_gosub_virtual_context"))) {
02506 ast_context_remove_extension2(con, "s", 1, NULL, 0);
02507 ast_context_destroy(con, "app_dial");
02508 }
02509
02510 return res;
02511 }
02512
02513 static int load_module(void)
02514 {
02515 int res;
02516 struct ast_context *con;
02517
02518 con = ast_context_find_or_create(NULL, NULL, "app_dial_gosub_virtual_context", "app_dial");
02519 if (!con)
02520 ast_log(LOG_ERROR, "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create\n");
02521 else
02522 ast_add_extension2(con, 1, "s", 1, NULL, NULL, "NoOp", ast_strdup(""), ast_free_ptr, "app_dial");
02523
02524 res = ast_register_application_xml(app, dial_exec);
02525 res |= ast_register_application_xml(rapp, retrydial_exec);
02526
02527 return res;
02528 }
02529
02530 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dialing Application");