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