#include "asterisk.h"
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/say.h"
#include "asterisk/config.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/callerid.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/causes.h"
#include "asterisk/rtp.h"
#include "asterisk/cdr.h"
#include "asterisk/manager.h"
#include "asterisk/privacy.h"
#include "asterisk/stringfields.h"
#include "asterisk/global_datastores.h"
Go to the source code of this file.
Data Structures | |
struct | dial_localuser |
Defines | |
#define | AST_MAX_WATCHERS 256 |
#define | CAN_EARLY_BRIDGE(flags, chan, peer) |
#define | DIAL_NOFORWARDHTML (1 << 31) |
#define | DIAL_STILLGOING (1 << 30) |
#define | HANDLE_CAUSE(cause, chan) |
Enumerations | |
enum | { OPT_ANNOUNCE = (1 << 0), OPT_RESETCDR = (1 << 1), OPT_DTMF_EXIT = (1 << 2), OPT_SENDDTMF = (1 << 3), OPT_FORCECLID = (1 << 4), OPT_GO_ON = (1 << 5), OPT_CALLEE_HANGUP = (1 << 6), OPT_CALLER_HANGUP = (1 << 7), OPT_PRIORITY_JUMP = (1 << 8), OPT_DURATION_LIMIT = (1 << 9), OPT_MUSICBACK = (1 << 10), OPT_CALLEE_MACRO = (1 << 11), OPT_SCREEN_NOINTRO = (1 << 12), OPT_SCREEN_NOCLID = (1 << 13), OPT_ORIGINAL_CLID = (1 << 14), OPT_SCREENING = (1 << 15), OPT_PRIVACY = (1 << 16), OPT_RINGBACK = (1 << 17), OPT_DURATION_STOP = (1 << 18), OPT_CALLEE_TRANSFER = (1 << 19), OPT_CALLER_TRANSFER = (1 << 20), OPT_CALLEE_MONITOR = (1 << 21), OPT_CALLER_MONITOR = (1 << 22), OPT_GOTO = (1 << 23), OPT_OPERMODE = (1 << 24), OPT_CALLEE_PARK = (1 << 25), OPT_CALLER_PARK = (1 << 26), OPT_IGNORE_FORWARDING = (1 << 27) } |
enum | { OPT_ARG_ANNOUNCE = 0, OPT_ARG_SENDDTMF, OPT_ARG_GOTO, OPT_ARG_DURATION_LIMIT, OPT_ARG_MUSICBACK, OPT_ARG_CALLEE_MACRO, OPT_ARG_PRIVACY, OPT_ARG_DURATION_STOP, OPT_ARG_OPERMODE, OPT_ARG_SCREEN_NOINTRO, OPT_ARG_ARRAY_SIZE } |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | detect_disconnect (struct ast_channel *chan, char code, char *featurecode, int len) |
static int | dial_exec (struct ast_channel *chan, void *data) |
static void | end_bridge_callback (void *data) |
static void | end_bridge_callback_data_fixup (struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator) |
static const char * | get_cid_name (char *name, int namelen, struct ast_channel *chan) |
static void | hanguptree (struct dial_localuser *outgoing, struct ast_channel *exception) |
static int | load_module (void) |
static int | onedigit_goto (struct ast_channel *chan, const char *context, char exten, int pri) |
static void | replace_macro_delimiter (char *s) |
static int | retrydial_exec (struct ast_channel *chan, void *data) |
static void | senddialevent (struct ast_channel *src, struct ast_channel *dst) |
static int | unload_module (void) |
static int | valid_priv_reply (struct ast_flags *opts, int res) |
static struct ast_channel * | wait_for_answer (struct ast_channel *in, struct dial_localuser *outgoing, int *to, struct ast_flags *peerflags, int *sentringing, char *status, size_t statussize, int busystart, int nochanstart, int congestionstart, int priority_jump, int *result) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Dialing Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } |
static char * | app = "Dial" |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static char * | descrip |
enum { ... } | dial_exec_option_args |
enum { ... } | dial_exec_option_flags |
static struct ast_app_option | dial_exec_options [128] = { [ 'A' ] = { .flag = OPT_ANNOUNCE , .arg_index = OPT_ARG_ANNOUNCE + 1 }, [ 'C' ] = { .flag = OPT_RESETCDR }, [ 'd' ] = { .flag = OPT_DTMF_EXIT }, [ 'D' ] = { .flag = OPT_SENDDTMF , .arg_index = OPT_ARG_SENDDTMF + 1 }, [ 'f' ] = { .flag = OPT_FORCECLID }, [ 'g' ] = { .flag = OPT_GO_ON }, [ 'G' ] = { .flag = OPT_GOTO , .arg_index = OPT_ARG_GOTO + 1 }, [ 'h' ] = { .flag = OPT_CALLEE_HANGUP }, [ 'H' ] = { .flag = OPT_CALLER_HANGUP }, [ 'i' ] = { .flag = OPT_IGNORE_FORWARDING }, [ 'j' ] = { .flag = OPT_PRIORITY_JUMP }, [ 'k' ] = { .flag = OPT_CALLEE_PARK }, [ 'K' ] = { .flag = OPT_CALLER_PARK }, [ 'L' ] = { .flag = OPT_DURATION_LIMIT , .arg_index = OPT_ARG_DURATION_LIMIT + 1 }, [ 'm' ] = { .flag = OPT_MUSICBACK , .arg_index = OPT_ARG_MUSICBACK + 1 }, [ 'M' ] = { .flag = OPT_CALLEE_MACRO , .arg_index = OPT_ARG_CALLEE_MACRO + 1 }, [ 'n' ] = { .flag = OPT_SCREEN_NOINTRO , .arg_index = OPT_ARG_SCREEN_NOINTRO + 1 }, [ 'N' ] = { .flag = OPT_SCREEN_NOCLID }, [ 'o' ] = { .flag = OPT_ORIGINAL_CLID }, [ 'O' ] = { .flag = OPT_OPERMODE , .arg_index = OPT_ARG_OPERMODE + 1 }, [ 'p' ] = { .flag = OPT_SCREENING }, [ 'P' ] = { .flag = OPT_PRIVACY , .arg_index = OPT_ARG_PRIVACY + 1 }, [ 'r' ] = { .flag = OPT_RINGBACK }, [ 'S' ] = { .flag = OPT_DURATION_STOP , .arg_index = OPT_ARG_DURATION_STOP + 1 }, [ 't' ] = { .flag = OPT_CALLEE_TRANSFER }, [ 'T' ] = { .flag = OPT_CALLER_TRANSFER }, [ 'w' ] = { .flag = OPT_CALLEE_MONITOR }, [ 'W' ] = { .flag = OPT_CALLER_MONITOR },} |
static char * | rapp = "RetryDial" |
static char * | rdescrip |
static char * | rsynopsis = "Place a call, retrying on failure allowing optional exit extension." |
static char * | synopsis = "Place a call and connect to the current channel" |
Definition in file app_dial.c.
#define AST_MAX_WATCHERS 256 |
Definition at line 344 of file app_dial.c.
#define CAN_EARLY_BRIDGE | ( | flags, | |||
chan, | |||||
peer | ) |
Value:
(!ast_test_flag(flags, OPT_CALLEE_HANGUP | \ OPT_CALLER_HANGUP | OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | \ OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | OPT_CALLEE_PARK | \ OPT_CALLER_PARK | OPT_ANNOUNCE | OPT_CALLEE_MACRO) && \ !chan->audiohooks && !peer->audiohooks)
Definition at line 313 of file app_dial.c.
Referenced by wait_for_answer().
#define DIAL_NOFORWARDHTML (1 << 31) |
#define DIAL_STILLGOING (1 << 30) |
#define HANDLE_CAUSE | ( | cause, | |||
chan | ) |
anonymous enum |
Definition at line 233 of file app_dial.c.
00233 { 00234 OPT_ANNOUNCE = (1 << 0), 00235 OPT_RESETCDR = (1 << 1), 00236 OPT_DTMF_EXIT = (1 << 2), 00237 OPT_SENDDTMF = (1 << 3), 00238 OPT_FORCECLID = (1 << 4), 00239 OPT_GO_ON = (1 << 5), 00240 OPT_CALLEE_HANGUP = (1 << 6), 00241 OPT_CALLER_HANGUP = (1 << 7), 00242 OPT_PRIORITY_JUMP = (1 << 8), 00243 OPT_DURATION_LIMIT = (1 << 9), 00244 OPT_MUSICBACK = (1 << 10), 00245 OPT_CALLEE_MACRO = (1 << 11), 00246 OPT_SCREEN_NOINTRO = (1 << 12), 00247 OPT_SCREEN_NOCLID = (1 << 13), 00248 OPT_ORIGINAL_CLID = (1 << 14), 00249 OPT_SCREENING = (1 << 15), 00250 OPT_PRIVACY = (1 << 16), 00251 OPT_RINGBACK = (1 << 17), 00252 OPT_DURATION_STOP = (1 << 18), 00253 OPT_CALLEE_TRANSFER = (1 << 19), 00254 OPT_CALLER_TRANSFER = (1 << 20), 00255 OPT_CALLEE_MONITOR = (1 << 21), 00256 OPT_CALLER_MONITOR = (1 << 22), 00257 OPT_GOTO = (1 << 23), 00258 OPT_OPERMODE = (1 << 24), 00259 OPT_CALLEE_PARK = (1 << 25), 00260 OPT_CALLER_PARK = (1 << 26), 00261 OPT_IGNORE_FORWARDING = (1 << 27), 00262 } dial_exec_option_flags;
anonymous enum |
Definition at line 267 of file app_dial.c.
00267 { 00268 OPT_ARG_ANNOUNCE = 0, 00269 OPT_ARG_SENDDTMF, 00270 OPT_ARG_GOTO, 00271 OPT_ARG_DURATION_LIMIT, 00272 OPT_ARG_MUSICBACK, 00273 OPT_ARG_CALLEE_MACRO, 00274 OPT_ARG_PRIVACY, 00275 OPT_ARG_DURATION_STOP, 00276 OPT_ARG_OPERMODE, 00277 OPT_ARG_SCREEN_NOINTRO, 00278 /* note: this entry _MUST_ be the last one in the enum */ 00279 OPT_ARG_ARRAY_SIZE, 00280 } dial_exec_option_args;
static void __reg_module | ( | void | ) | [static] |
Definition at line 2060 of file app_dial.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 2060 of file app_dial.c.
static int detect_disconnect | ( | struct ast_channel * | chan, | |
char | code, | |||
char * | featurecode, | |||
int | len | |||
) | [static] |
Definition at line 811 of file app_dial.c.
References ast_feature_detect(), AST_FEATURE_DISCONNECT, ast_call_feature::feature_mask, and FEATURE_RETURN_STOREDIGITS.
Referenced by wait_for_answer().
00812 { 00813 struct ast_flags features = { AST_FEATURE_DISCONNECT }; /* only concerned with disconnect feature */ 00814 struct ast_call_feature feature = { 0, }; 00815 char *tmp; 00816 int res; 00817 00818 if ((strlen(featurecode)) < (len - 2)) { 00819 tmp = &featurecode[strlen(featurecode)]; 00820 tmp[0] = code; 00821 tmp[1] = '\0'; 00822 } else { 00823 featurecode[0] = 0; 00824 return -1; /* no room in featurecode buffer */ 00825 } 00826 00827 res = ast_feature_detect(chan, &features, featurecode, &feature); 00828 00829 if (res != FEATURE_RETURN_STOREDIGITS) { 00830 featurecode[0] = '\0'; 00831 } 00832 if (feature.feature_mask & AST_FEATURE_DISCONNECT) { 00833 return 1; 00834 } 00835 00836 return 0; 00837 }
static int dial_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 1913 of file app_dial.c.
Referenced by load_module().
01914 { 01915 struct ast_flags peerflags; 01916 01917 memset(&peerflags, 0, sizeof(peerflags)); 01918 01919 return dial_exec_full(chan, data, &peerflags, NULL); 01920 }
static void end_bridge_callback | ( | void * | data | ) | [static] |
Definition at line 859 of file app_dial.c.
References ast_cdr::answer, ast_channel_lock, ast_channel_unlock, ast_channel::cdr, pbx_builtin_setvar_helper(), and ast_cdr::start.
Referenced by app_exec().
00860 { 00861 char buf[80]; 00862 time_t end; 00863 struct ast_channel *chan = data; 00864 00865 if (!chan->cdr) { 00866 return; 00867 } 00868 00869 time(&end); 00870 00871 ast_channel_lock(chan); 00872 if (chan->cdr->answer.tv_sec) { 00873 snprintf(buf, sizeof(buf), "%ld", end - chan->cdr->answer.tv_sec); 00874 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf); 00875 } 00876 00877 if (chan->cdr->start.tv_sec) { 00878 snprintf(buf, sizeof(buf), "%ld", end - chan->cdr->start.tv_sec); 00879 pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf); 00880 } 00881 ast_channel_unlock(chan); 00882 }
static void end_bridge_callback_data_fixup | ( | struct ast_bridge_config * | bconfig, | |
struct ast_channel * | originator, | |||
struct ast_channel * | terminator | |||
) | [static] |
Definition at line 884 of file app_dial.c.
References ast_bridge_config::end_bridge_callback_data.
Referenced by app_exec().
00884 { 00885 bconfig->end_bridge_callback_data = originator; 00886 }
static const char* get_cid_name | ( | char * | name, | |
int | namelen, | |||
struct ast_channel * | chan | |||
) | [static] |
Definition at line 397 of file app_dial.c.
References ast_get_hint(), dial_localuser::chan, ast_channel::context, context, ast_channel::exten, exten, ast_channel::macrocontext, ast_channel::macroexten, and S_OR.
Referenced by wait_for_answer().
00398 { 00399 const char *context = S_OR(chan->macrocontext, chan->context); 00400 const char *exten = S_OR(chan->macroexten, chan->exten); 00401 00402 return ast_get_hint(NULL, 0, name, namelen, chan, context, exten) ? name : ""; 00403 }
static void hanguptree | ( | struct dial_localuser * | outgoing, | |
struct ast_channel * | exception | |||
) | [static] |
Definition at line 330 of file app_dial.c.
References ast_hangup(), dial_localuser::chan, free, and dial_localuser::next.
00331 { 00332 /* Hang up a tree of stuff */ 00333 struct dial_localuser *oo; 00334 while (outgoing) { 00335 /* Hangup any existing lines we have open */ 00336 if (outgoing->chan && (outgoing->chan != exception)) 00337 ast_hangup(outgoing->chan); 00338 oo = outgoing; 00339 outgoing=outgoing->next; 00340 free(oo); 00341 } 00342 }
static int load_module | ( | void | ) | [static] |
Definition at line 2050 of file app_dial.c.
References ast_register_application(), dial_exec(), and retrydial_exec().
02051 { 02052 int res; 02053 02054 res = ast_register_application(app, dial_exec, synopsis, descrip); 02055 res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip); 02056 02057 return res; 02058 }
static int onedigit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
char | exten, | |||
int | pri | |||
) | [static] |
Definition at line 377 of file app_dial.c.
References ast_goto_if_exists(), ast_strlen_zero(), dial_localuser::chan, ast_channel::context, and ast_channel::macrocontext.
Referenced by retrydial_exec(), and wait_for_answer().
00378 { 00379 char rexten[2] = { exten, '\0' }; 00380 00381 if (context) { 00382 if (!ast_goto_if_exists(chan, context, rexten, pri)) 00383 return 1; 00384 } else { 00385 if (!ast_goto_if_exists(chan, chan->context, rexten, pri)) 00386 return 1; 00387 else if (!ast_strlen_zero(chan->macrocontext)) { 00388 if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri)) 00389 return 1; 00390 } 00391 } 00392 return 0; 00393 }
static void replace_macro_delimiter | ( | char * | s | ) | [static] |
static int retrydial_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 1922 of file app_dial.c.
References AST_DIGIT_ANY, ast_fileexists(), AST_FLAG_MOH, ast_log(), ast_module_user_add, ast_module_user_remove, ast_moh_start(), ast_moh_stop(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_waitfordigit(), ast_waitstream(), context, ast_channel::data, LOG_ERROR, LOG_WARNING, onedigit_goto(), OPT_DTMF_EXIT, and pbx_builtin_getvar_helper().
Referenced by load_module().
01923 { 01924 char *announce = NULL, *dialdata = NULL; 01925 const char *context = NULL; 01926 int sleep = 0, loops = 0, res = -1; 01927 struct ast_module_user *u; 01928 struct ast_flags peerflags; 01929 01930 if (ast_strlen_zero(data)) { 01931 ast_log(LOG_WARNING, "RetryDial requires an argument!\n"); 01932 return -1; 01933 } 01934 01935 u = ast_module_user_add(chan); 01936 01937 announce = ast_strdupa(data); 01938 01939 memset(&peerflags, 0, sizeof(peerflags)); 01940 01941 if ((dialdata = strchr(announce, '|'))) { 01942 *dialdata++ = '\0'; 01943 if (sscanf(dialdata, "%30d", &sleep) == 1) { 01944 sleep *= 1000; 01945 } else { 01946 ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp); 01947 goto done; 01948 } 01949 if ((dialdata = strchr(dialdata, '|'))) { 01950 *dialdata++ = '\0'; 01951 if (sscanf(dialdata, "%30d", &loops) != 1) { 01952 ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp); 01953 goto done; 01954 } 01955 } 01956 } 01957 01958 if (dialdata && (dialdata = strchr(dialdata, '|'))) { 01959 *dialdata++ = '\0'; 01960 } else { 01961 ast_log(LOG_ERROR, "%s requires more arguments\n",rapp); 01962 goto done; 01963 } 01964 01965 if (sleep < 1000) 01966 sleep = 10000; 01967 01968 if (!loops) 01969 loops = -1; /* run forever */ 01970 01971 context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT"); 01972 01973 res = 0; 01974 while (loops) { 01975 int continue_exec; 01976 01977 chan->data = "Retrying"; 01978 if (ast_test_flag(chan, AST_FLAG_MOH)) 01979 ast_moh_stop(chan); 01980 01981 res = dial_exec_full(chan, dialdata, &peerflags, &continue_exec); 01982 if (continue_exec) 01983 break; 01984 01985 if (res == 0) { 01986 if (ast_test_flag(&peerflags, OPT_DTMF_EXIT)) { 01987 if (!ast_strlen_zero(announce)) { 01988 if (ast_fileexists(announce, NULL, chan->language) > 0) { 01989 if(!(res = ast_streamfile(chan, announce, chan->language))) 01990 ast_waitstream(chan, AST_DIGIT_ANY); 01991 } else 01992 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", announce); 01993 } 01994 if (!res && sleep) { 01995 if (!ast_test_flag(chan, AST_FLAG_MOH)) 01996 ast_moh_start(chan, NULL, NULL); 01997 res = ast_waitfordigit(chan, sleep); 01998 } 01999 } else { 02000 if (!ast_strlen_zero(announce)) { 02001 if (ast_fileexists(announce, NULL, chan->language) > 0) { 02002 if (!(res = ast_streamfile(chan, announce, chan->language))) 02003 res = ast_waitstream(chan, ""); 02004 } else 02005 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", announce); 02006 } 02007 if (sleep) { 02008 if (!ast_test_flag(chan, AST_FLAG_MOH)) 02009 ast_moh_start(chan, NULL, NULL); 02010 if (!res) 02011 res = ast_waitfordigit(chan, sleep); 02012 } 02013 } 02014 } 02015 02016 if (res < 0) 02017 break; 02018 else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */ 02019 if (onedigit_goto(chan, context, (char) res, 1)) { 02020 res = 0; 02021 break; 02022 } 02023 } 02024 loops--; 02025 } 02026 if (loops == 0) 02027 res = 0; 02028 else if (res == 1) 02029 res = 0; 02030 02031 if (ast_test_flag(chan, AST_FLAG_MOH)) 02032 ast_moh_stop(chan); 02033 done: 02034 ast_module_user_remove(u); 02035 return res; 02036 }
static void senddialevent | ( | struct ast_channel * | src, | |
struct ast_channel * | dst | |||
) | [static] |
Definition at line 405 of file app_dial.c.
References ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, EVENT_FLAG_CALL, manager_event(), ast_channel::name, S_OR, and ast_channel::uniqueid.
Referenced by wait_for_answer().
00406 { 00407 /* XXX do we need also CallerIDnum ? */ 00408 manager_event(EVENT_FLAG_CALL, "Dial", 00409 "Source: %s\r\n" 00410 "Destination: %s\r\n" 00411 "CallerID: %s\r\n" 00412 "CallerIDName: %s\r\n" 00413 "SrcUniqueID: %s\r\n" 00414 "DestUniqueID: %s\r\n", 00415 src->name, dst->name, S_OR(src->cid.cid_num, "<unknown>"), 00416 S_OR(src->cid.cid_name, "<unknown>"), src->uniqueid, 00417 dst->uniqueid); 00418 }
static int unload_module | ( | void | ) | [static] |
Definition at line 2038 of file app_dial.c.
References ast_module_user_hangup_all, and ast_unregister_application().
02039 { 02040 int res; 02041 02042 res = ast_unregister_application(app); 02043 res |= ast_unregister_application(rapp); 02044 02045 ast_module_user_hangup_all(); 02046 02047 return res; 02048 }
static int valid_priv_reply | ( | struct ast_flags * | opts, | |
int | res | |||
) | [static] |
Definition at line 848 of file app_dial.c.
References ast_test_flag, OPT_PRIVACY, and OPT_SCREENING.
00849 { 00850 if (res < '1') 00851 return 0; 00852 if (ast_test_flag(opts, OPT_PRIVACY) && res <= '5') 00853 return 1; 00854 if (ast_test_flag(opts, OPT_SCREENING) && res <= '4') 00855 return 1; 00856 return 0; 00857 }
static struct ast_channel* wait_for_answer | ( | struct ast_channel * | in, | |
struct dial_localuser * | outgoing, | |||
int * | to, | |||
struct ast_flags * | peerflags, | |||
int * | sentringing, | |||
char * | status, | |||
size_t | statussize, | |||
int | busystart, | |||
int | nochanstart, | |||
int | congestionstart, | |||
int | priority_jump, | |||
int * | result | |||
) | [static] |
Definition at line 420 of file app_dial.c.
References ast_channel::_state, ast_channel::accountcode, accountcode, ast_cdr::answer, ast_call(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CDR_ANSWERED, ast_cdr_noanswer(), ast_channel_datastore_inherit(), ast_channel_inherit_variables(), ast_channel_make_compatible(), ast_channel_sendhtml(), ast_check_hangup(), ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_copy_flags, ast_copy_string(), ast_deactivate_generator(), AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_TEXT, AST_FRAME_VOICE, ast_frfree, ast_goto_if_exists(), ast_hangup(), ast_indicate(), ast_indicate_data(), ast_log(), AST_MAX_EXTENSION, AST_MAX_WATCHERS, ast_opt_priority_jumping, ast_read(), ast_request(), ast_rtp_early_bridge(), ast_rtp_make_compatible(), ast_set_callerid(), AST_STATE_UP, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_tvnow(), ast_verbose(), ast_waitfor_n(), ast_write(), CAN_EARLY_BRIDGE, ast_channel::cdr, ast_channel::cdrflags, dial_localuser::chan, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, context, ast_channel::context, detect_disconnect(), DIAL_NOFORWARDHTML, DIAL_STILLGOING, ast_channel::dialcontext, ast_cdr::disposition, ast_channel::exten, f, FEATURE_MAX_LEN, free, get_cid_name(), HANDLE_CAUSE, ast_channel::hangupcause, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::macroexten, ast_channel::name, ast_channel::nativeformats, dial_localuser::next, onedigit_goto(), OPT_CALLEE_HANGUP, OPT_CALLEE_MONITOR, OPT_CALLEE_PARK, OPT_CALLEE_TRANSFER, OPT_CALLER_HANGUP, OPT_CALLER_MONITOR, OPT_CALLER_PARK, OPT_CALLER_TRANSFER, OPT_DTMF_EXIT, OPT_FORCECLID, OPT_IGNORE_FORWARDING, OPT_MUSICBACK, OPT_ORIGINAL_CLID, OPT_RINGBACK, option_debug, option_verbose, pbx_builtin_getvar_helper(), S_OR, senddialevent(), ast_channel::tech, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.
Referenced by try_calling().
00421 { 00422 int numbusy = busystart; 00423 int numcongestion = congestionstart; 00424 int numnochan = nochanstart; 00425 int prestart = busystart + congestionstart + nochanstart; 00426 int orig = *to; 00427 struct ast_channel *peer = NULL; 00428 /* single is set if only one destination is enabled */ 00429 int single = outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK); 00430 00431 char featurecode[FEATURE_MAX_LEN + 1] = { 0, }; 00432 00433 if (single) { 00434 /* Turn off hold music, etc */ 00435 ast_deactivate_generator(in); 00436 /* If we are calling a single channel, make them compatible for in-band tone purpose */ 00437 ast_channel_make_compatible(outgoing->chan, in); 00438 } 00439 00440 00441 while (*to && !peer) { 00442 struct dial_localuser *o; 00443 int pos = 0; /* how many channels do we handle */ 00444 int numlines = prestart; 00445 struct ast_channel *winner; 00446 struct ast_channel *watchers[AST_MAX_WATCHERS]; 00447 00448 watchers[pos++] = in; 00449 for (o = outgoing; o; o = o->next) { 00450 /* Keep track of important channels */ 00451 if (ast_test_flag(o, DIAL_STILLGOING) && o->chan) 00452 watchers[pos++] = o->chan; 00453 numlines++; 00454 } 00455 if (pos == 1) { /* only the input channel is available */ 00456 if (numlines == (numbusy + numcongestion + numnochan)) { 00457 if (option_verbose > 2) 00458 ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan); 00459 if (numbusy) 00460 strcpy(status, "BUSY"); 00461 else if (numcongestion) 00462 strcpy(status, "CONGESTION"); 00463 else if (numnochan) 00464 strcpy(status, "CHANUNAVAIL"); 00465 if (ast_opt_priority_jumping || priority_jump) 00466 ast_goto_if_exists(in, in->context, in->exten, in->priority + 101); 00467 } else { 00468 if (option_verbose > 2) 00469 ast_verbose(VERBOSE_PREFIX_3 "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan); 00470 } 00471 *to = 0; 00472 return NULL; 00473 } 00474 winner = ast_waitfor_n(watchers, pos, to); 00475 for (o = outgoing; o; o = o->next) { 00476 struct ast_frame *f; 00477 struct ast_channel *c = o->chan; 00478 00479 if (c == NULL) 00480 continue; 00481 if (ast_test_flag(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) { 00482 if (!peer) { 00483 if (option_verbose > 2) 00484 ast_verbose(VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name); 00485 peer = c; 00486 ast_copy_flags(peerflags, o, 00487 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 00488 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 00489 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 00490 OPT_CALLEE_PARK | OPT_CALLER_PARK | 00491 DIAL_NOFORWARDHTML); 00492 ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext)); 00493 ast_copy_string(c->exten, "", sizeof(c->exten)); 00494 } 00495 continue; 00496 } 00497 if (c != winner) 00498 continue; 00499 if (!ast_strlen_zero(c->call_forward)) { 00500 char tmpchan[256]; 00501 char *stuff; 00502 char *tech; 00503 int cause; 00504 00505 ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan)); 00506 if ((stuff = strchr(tmpchan, '/'))) { 00507 *stuff++ = '\0'; 00508 tech = tmpchan; 00509 } else { 00510 const char *forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT"); 00511 if (ast_strlen_zero(forward_context)) { 00512 forward_context = NULL; 00513 } 00514 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context); 00515 stuff = tmpchan; 00516 tech = "Local"; 00517 } 00518 /* Before processing channel, go ahead and check for forwarding */ 00519 if (option_verbose > 2) 00520 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name); 00521 /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */ 00522 if (ast_test_flag(peerflags, OPT_IGNORE_FORWARDING)) { 00523 if (option_verbose > 2) 00524 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff); 00525 c = o->chan = NULL; 00526 cause = AST_CAUSE_BUSY; 00527 } else { 00528 /* Setup parameters */ 00529 if ((c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause))) { 00530 if (single) 00531 ast_channel_make_compatible(o->chan, in); 00532 ast_channel_inherit_variables(in, o->chan); 00533 ast_channel_datastore_inherit(in, o->chan); 00534 } else 00535 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause); 00536 } 00537 if (!c) { 00538 ast_clear_flag(o, DIAL_STILLGOING); 00539 HANDLE_CAUSE(cause, in); 00540 } else { 00541 if (CAN_EARLY_BRIDGE(peerflags, c, in)) { 00542 ast_rtp_make_compatible(c, in, single); 00543 } 00544 if (c->cid.cid_num) 00545 free(c->cid.cid_num); 00546 c->cid.cid_num = NULL; 00547 if (c->cid.cid_name) 00548 free(c->cid.cid_name); 00549 c->cid.cid_name = NULL; 00550 00551 if (ast_test_flag(o, OPT_FORCECLID)) { 00552 c->cid.cid_num = ast_strdup(S_OR(in->macroexten, in->exten)); 00553 ast_string_field_set(c, accountcode, winner->accountcode); 00554 c->cdrflags = winner->cdrflags; 00555 } else { 00556 c->cid.cid_num = ast_strdup(in->cid.cid_num); 00557 c->cid.cid_name = ast_strdup(in->cid.cid_name); 00558 ast_string_field_set(c, accountcode, in->accountcode); 00559 c->cdrflags = in->cdrflags; 00560 } 00561 00562 if (in->cid.cid_ani) { 00563 if (c->cid.cid_ani) 00564 free(c->cid.cid_ani); 00565 c->cid.cid_ani = ast_strdup(in->cid.cid_ani); 00566 } 00567 if (c->cid.cid_rdnis) 00568 free(c->cid.cid_rdnis); 00569 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_flag(o, DIAL_STILLGOING); 00573 ast_hangup(c); 00574 c = o->chan = NULL; 00575 numnochan++; 00576 } else { 00577 senddialevent(in, c); 00578 /* After calling, set callerid to extension */ 00579 if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID)) { 00580 char cidname[AST_MAX_EXTENSION] = ""; 00581 ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL); 00582 } 00583 } 00584 if (single) { 00585 ast_indicate(in, -1); 00586 } 00587 } 00588 /* Hangup the original channel now, in case we needed it */ 00589 ast_hangup(winner); 00590 continue; 00591 } 00592 f = ast_read(winner); 00593 if (!f) { 00594 in->hangupcause = c->hangupcause; 00595 ast_hangup(c); 00596 c = o->chan = NULL; 00597 ast_clear_flag(o, DIAL_STILLGOING); 00598 HANDLE_CAUSE(in->hangupcause, in); 00599 continue; 00600 } 00601 if (f->frametype == AST_FRAME_CONTROL) { 00602 switch(f->subclass) { 00603 case AST_CONTROL_ANSWER: 00604 /* This is our guy if someone answered. */ 00605 if (!peer) { 00606 if (option_verbose > 2) 00607 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name); 00608 peer = c; 00609 if (peer->cdr) { 00610 peer->cdr->answer = ast_tvnow(); 00611 peer->cdr->disposition = AST_CDR_ANSWERED; 00612 } 00613 ast_copy_flags(peerflags, o, 00614 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 00615 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 00616 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 00617 OPT_CALLEE_PARK | OPT_CALLER_PARK | 00618 DIAL_NOFORWARDHTML); 00619 ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext)); 00620 ast_copy_string(c->exten, "", sizeof(c->exten)); 00621 /* Setup RTP early bridge if appropriate */ 00622 if (CAN_EARLY_BRIDGE(peerflags, in, peer)) 00623 ast_rtp_early_bridge(in, peer); 00624 } 00625 /* If call has been answered, then the eventual hangup is likely to be normal hangup */ 00626 in->hangupcause = AST_CAUSE_NORMAL_CLEARING; 00627 c->hangupcause = AST_CAUSE_NORMAL_CLEARING; 00628 break; 00629 case AST_CONTROL_BUSY: 00630 if (option_verbose > 2) 00631 ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", c->name); 00632 in->hangupcause = c->hangupcause; 00633 ast_hangup(c); 00634 c = o->chan = NULL; 00635 ast_clear_flag(o, DIAL_STILLGOING); 00636 HANDLE_CAUSE(AST_CAUSE_BUSY, in); 00637 break; 00638 case AST_CONTROL_CONGESTION: 00639 if (option_verbose > 2) 00640 ast_verbose(VERBOSE_PREFIX_3 "%s is circuit-busy\n", c->name); 00641 in->hangupcause = c->hangupcause; 00642 ast_hangup(c); 00643 c = o->chan = NULL; 00644 ast_clear_flag(o, DIAL_STILLGOING); 00645 HANDLE_CAUSE(AST_CAUSE_CONGESTION, in); 00646 break; 00647 case AST_CONTROL_RINGING: 00648 if (option_verbose > 2) 00649 ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", c->name); 00650 /* Setup early media if appropriate */ 00651 if (single && CAN_EARLY_BRIDGE(peerflags, in, c)) 00652 ast_rtp_early_bridge(in, c); 00653 if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) { 00654 ast_indicate(in, AST_CONTROL_RINGING); 00655 (*sentringing)++; 00656 } 00657 break; 00658 case AST_CONTROL_PROGRESS: 00659 if (option_verbose > 2) 00660 ast_verbose (VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", c->name, in->name); 00661 /* Setup early media if appropriate */ 00662 if (single && CAN_EARLY_BRIDGE(peerflags, in, c)) 00663 ast_rtp_early_bridge(in, c); 00664 if (!ast_test_flag(outgoing, OPT_RINGBACK)) { 00665 if (single || (!single && !(*sentringing))) { 00666 /* want progress to go through if it's a single legged call or it's a 00667 * branched call and ringing has not been sent */ 00668 ast_indicate(in, AST_CONTROL_PROGRESS); 00669 } 00670 } 00671 break; 00672 case AST_CONTROL_VIDUPDATE: 00673 if (option_verbose > 2) 00674 ast_verbose (VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", c->name, in->name); 00675 ast_indicate(in, AST_CONTROL_VIDUPDATE); 00676 break; 00677 case AST_CONTROL_SRCUPDATE: 00678 if (option_verbose > 2) 00679 ast_verbose (VERBOSE_PREFIX_3 "%s requested a source update, passing it to %s\n", c->name, in->name); 00680 ast_indicate(in, AST_CONTROL_SRCUPDATE); 00681 break; 00682 case AST_CONTROL_PROCEEDING: 00683 if (option_verbose > 2) 00684 ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", c->name, in->name); 00685 if (single && CAN_EARLY_BRIDGE(peerflags, in, c)) 00686 ast_rtp_early_bridge(in, c); 00687 if (!ast_test_flag(outgoing, OPT_RINGBACK)) 00688 ast_indicate(in, AST_CONTROL_PROCEEDING); 00689 break; 00690 case AST_CONTROL_HOLD: 00691 if (option_verbose > 2) 00692 ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", c->name); 00693 ast_indicate(in, AST_CONTROL_HOLD); 00694 break; 00695 case AST_CONTROL_UNHOLD: 00696 if (option_verbose > 2) 00697 ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", c->name); 00698 ast_indicate(in, AST_CONTROL_UNHOLD); 00699 break; 00700 case AST_CONTROL_OFFHOOK: 00701 case AST_CONTROL_FLASH: 00702 /* Ignore going off hook and flash */ 00703 break; 00704 case -1: 00705 if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) { 00706 if (option_verbose > 2) 00707 ast_verbose(VERBOSE_PREFIX_3 "%s stopped sounds\n", c->name); 00708 ast_indicate(in, -1); 00709 (*sentringing) = 0; 00710 } 00711 break; 00712 default: 00713 if (option_debug) 00714 ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass); 00715 } 00716 } else if (single) { 00717 /* XXX are we sure the logic is correct ? or we should just switch on f->frametype ? */ 00718 if (f->frametype == AST_FRAME_VOICE && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) { 00719 if (ast_write(in, f)) 00720 ast_log(LOG_WARNING, "Unable to forward voice frame\n"); 00721 } else if (f->frametype == AST_FRAME_IMAGE && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) { 00722 if (ast_write(in, f)) 00723 ast_log(LOG_WARNING, "Unable to forward image\n"); 00724 } else if (f->frametype == AST_FRAME_TEXT && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) { 00725 if (ast_write(in, f)) 00726 ast_log(LOG_WARNING, "Unable to send text\n"); 00727 } else if (f->frametype == AST_FRAME_HTML && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) { 00728 if (ast_channel_sendhtml(in, f->subclass, f->data, f->datalen) == -1) 00729 ast_log(LOG_WARNING, "Unable to send URL\n"); 00730 } 00731 } 00732 ast_frfree(f); 00733 } /* end for */ 00734 if (winner == in) { 00735 struct ast_frame *f = ast_read(in); 00736 #if 0 00737 if (f && (f->frametype != AST_FRAME_VOICE)) 00738 printf("Frame type: %d, %d\n", f->frametype, f->subclass); 00739 else if (!f || (f->frametype != AST_FRAME_VOICE)) 00740 printf("Hangup received on %s\n", in->name); 00741 #endif 00742 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) { 00743 /* Got hung up */ 00744 *to = -1; 00745 ast_cdr_noanswer(in->cdr); 00746 strcpy(status, "CANCEL"); 00747 if (f) 00748 ast_frfree(f); 00749 return NULL; 00750 } 00751 00752 if (f && (f->frametype == AST_FRAME_DTMF)) { 00753 if (ast_test_flag(peerflags, OPT_DTMF_EXIT)) { 00754 const char *context = pbx_builtin_getvar_helper(in, "EXITCONTEXT"); 00755 if (onedigit_goto(in, context, (char) f->subclass, 1)) { 00756 if (option_verbose > 2) 00757 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass); 00758 *to=0; 00759 ast_cdr_noanswer(in->cdr); 00760 *result = f->subclass; 00761 strcpy(status, "CANCEL"); 00762 ast_frfree(f); 00763 return NULL; 00764 } 00765 } 00766 00767 if (ast_test_flag(peerflags, OPT_CALLER_HANGUP) && 00768 detect_disconnect(in, f->subclass, featurecode, sizeof(featurecode))) { 00769 if (option_verbose > 2) 00770 ast_verbose(VERBOSE_PREFIX_3 "User requested call disconnect.\n"); 00771 *to=0; 00772 ast_cdr_noanswer(in->cdr); 00773 strcpy(status, "CANCEL"); 00774 ast_frfree(f); 00775 return NULL; 00776 } 00777 } 00778 00779 /* Forward HTML stuff */ 00780 if (single && f && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) 00781 if(ast_channel_sendhtml(outgoing->chan, f->subclass, f->data, f->datalen) == -1) 00782 ast_log(LOG_WARNING, "Unable to send URL\n"); 00783 00784 00785 if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF_BEGIN) || (f->frametype == AST_FRAME_DTMF_END))) { 00786 if (ast_write(outgoing->chan, f)) 00787 ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n"); 00788 } 00789 if (single && (f->frametype == AST_FRAME_CONTROL) && 00790 ((f->subclass == AST_CONTROL_HOLD) || 00791 (f->subclass == AST_CONTROL_UNHOLD) || 00792 (f->subclass == AST_CONTROL_VIDUPDATE) || 00793 (f->subclass == AST_CONTROL_SRCUPDATE))) { 00794 if (option_verbose > 2) 00795 ast_verbose(VERBOSE_PREFIX_3 "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name); 00796 ast_indicate_data(outgoing->chan, f->subclass, f->data, f->datalen); 00797 } 00798 ast_frfree(f); 00799 } 00800 if (!*to && (option_verbose > 2)) 00801 ast_verbose(VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig); 00802 if (!*to || ast_check_hangup(in)) { 00803 ast_cdr_noanswer(in->cdr); 00804 } 00805 00806 } 00807 00808 return peer; 00809 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Dialing Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 2060 of file app_dial.c.
char* app = "Dial" [static] |
Definition at line 71 of file app_dial.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 2060 of file app_dial.c.
char* descrip [static] |
Definition at line 75 of file app_dial.c.
enum { ... } dial_exec_option_args |
enum { ... } dial_exec_option_flags |
struct ast_app_option dial_exec_options[128] = { [ 'A' ] = { .flag = OPT_ANNOUNCE , .arg_index = OPT_ARG_ANNOUNCE + 1 }, [ 'C' ] = { .flag = OPT_RESETCDR }, [ 'd' ] = { .flag = OPT_DTMF_EXIT }, [ 'D' ] = { .flag = OPT_SENDDTMF , .arg_index = OPT_ARG_SENDDTMF + 1 }, [ 'f' ] = { .flag = OPT_FORCECLID }, [ 'g' ] = { .flag = OPT_GO_ON }, [ 'G' ] = { .flag = OPT_GOTO , .arg_index = OPT_ARG_GOTO + 1 }, [ 'h' ] = { .flag = OPT_CALLEE_HANGUP }, [ 'H' ] = { .flag = OPT_CALLER_HANGUP }, [ 'i' ] = { .flag = OPT_IGNORE_FORWARDING }, [ 'j' ] = { .flag = OPT_PRIORITY_JUMP }, [ 'k' ] = { .flag = OPT_CALLEE_PARK }, [ 'K' ] = { .flag = OPT_CALLER_PARK }, [ 'L' ] = { .flag = OPT_DURATION_LIMIT , .arg_index = OPT_ARG_DURATION_LIMIT + 1 }, [ 'm' ] = { .flag = OPT_MUSICBACK , .arg_index = OPT_ARG_MUSICBACK + 1 }, [ 'M' ] = { .flag = OPT_CALLEE_MACRO , .arg_index = OPT_ARG_CALLEE_MACRO + 1 }, [ 'n' ] = { .flag = OPT_SCREEN_NOINTRO , .arg_index = OPT_ARG_SCREEN_NOINTRO + 1 }, [ 'N' ] = { .flag = OPT_SCREEN_NOCLID }, [ 'o' ] = { .flag = OPT_ORIGINAL_CLID }, [ 'O' ] = { .flag = OPT_OPERMODE , .arg_index = OPT_ARG_OPERMODE + 1 }, [ 'p' ] = { .flag = OPT_SCREENING }, [ 'P' ] = { .flag = OPT_PRIVACY , .arg_index = OPT_ARG_PRIVACY + 1 }, [ 'r' ] = { .flag = OPT_RINGBACK }, [ 'S' ] = { .flag = OPT_DURATION_STOP , .arg_index = OPT_ARG_DURATION_STOP + 1 }, [ 't' ] = { .flag = OPT_CALLEE_TRANSFER }, [ 'T' ] = { .flag = OPT_CALLER_TRANSFER }, [ 'w' ] = { .flag = OPT_CALLEE_MONITOR }, [ 'W' ] = { .flag = OPT_CALLER_MONITOR },} [static] |
Definition at line 311 of file app_dial.c.
char* rapp = "RetryDial" [static] |
Definition at line 218 of file app_dial.c.
char* rdescrip [static] |
Definition at line 220 of file app_dial.c.
char* rsynopsis = "Place a call, retrying on failure allowing optional exit extension." [static] |
Definition at line 219 of file app_dial.c.
char* synopsis = "Place a call and connect to the current channel" [static] |
Definition at line 73 of file app_dial.c.