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