#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_ARRAY_SIZE } |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
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 = "f450f61f60e761b3aa089ebed76ca8a5" , .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 }, [ '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 339 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) && \ !chan->audiohooks && !peer->audiohooks)
Definition at line 309 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 230 of file app_dial.c.
00230 { 00231 OPT_ANNOUNCE = (1 << 0), 00232 OPT_RESETCDR = (1 << 1), 00233 OPT_DTMF_EXIT = (1 << 2), 00234 OPT_SENDDTMF = (1 << 3), 00235 OPT_FORCECLID = (1 << 4), 00236 OPT_GO_ON = (1 << 5), 00237 OPT_CALLEE_HANGUP = (1 << 6), 00238 OPT_CALLER_HANGUP = (1 << 7), 00239 OPT_PRIORITY_JUMP = (1 << 8), 00240 OPT_DURATION_LIMIT = (1 << 9), 00241 OPT_MUSICBACK = (1 << 10), 00242 OPT_CALLEE_MACRO = (1 << 11), 00243 OPT_SCREEN_NOINTRO = (1 << 12), 00244 OPT_SCREEN_NOCLID = (1 << 13), 00245 OPT_ORIGINAL_CLID = (1 << 14), 00246 OPT_SCREENING = (1 << 15), 00247 OPT_PRIVACY = (1 << 16), 00248 OPT_RINGBACK = (1 << 17), 00249 OPT_DURATION_STOP = (1 << 18), 00250 OPT_CALLEE_TRANSFER = (1 << 19), 00251 OPT_CALLER_TRANSFER = (1 << 20), 00252 OPT_CALLEE_MONITOR = (1 << 21), 00253 OPT_CALLER_MONITOR = (1 << 22), 00254 OPT_GOTO = (1 << 23), 00255 OPT_OPERMODE = (1 << 24), 00256 OPT_CALLEE_PARK = (1 << 25), 00257 OPT_CALLER_PARK = (1 << 26), 00258 OPT_IGNORE_FORWARDING = (1 << 27), 00259 } dial_exec_option_flags;
anonymous enum |
OPT_ARG_ANNOUNCE | |
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_ARRAY_SIZE |
Definition at line 264 of file app_dial.c.
00264 { 00265 OPT_ARG_ANNOUNCE = 0, 00266 OPT_ARG_SENDDTMF, 00267 OPT_ARG_GOTO, 00268 OPT_ARG_DURATION_LIMIT, 00269 OPT_ARG_MUSICBACK, 00270 OPT_ARG_CALLEE_MACRO, 00271 OPT_ARG_PRIVACY, 00272 OPT_ARG_DURATION_STOP, 00273 OPT_ARG_OPERMODE, 00274 /* note: this entry _MUST_ be the last one in the enum */ 00275 OPT_ARG_ARRAY_SIZE, 00276 } dial_exec_option_args;
static void __reg_module | ( | void | ) | [static] |
Definition at line 1945 of file app_dial.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1945 of file app_dial.c.
static int dial_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 1798 of file app_dial.c.
Referenced by load_module().
01799 { 01800 struct ast_flags peerflags; 01801 01802 memset(&peerflags, 0, sizeof(peerflags)); 01803 01804 return dial_exec_full(chan, data, &peerflags, NULL); 01805 }
static void end_bridge_callback | ( | void * | data | ) | [static] |
Definition at line 809 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().
00810 { 00811 char buf[80]; 00812 time_t end; 00813 struct ast_channel *chan = data; 00814 00815 if (!chan->cdr) { 00816 return; 00817 } 00818 00819 time(&end); 00820 00821 ast_channel_lock(chan); 00822 if (chan->cdr->answer.tv_sec) { 00823 snprintf(buf, sizeof(buf), "%ld", end - chan->cdr->answer.tv_sec); 00824 pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf); 00825 } 00826 00827 if (chan->cdr->start.tv_sec) { 00828 snprintf(buf, sizeof(buf), "%ld", end - chan->cdr->start.tv_sec); 00829 pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf); 00830 } 00831 ast_channel_unlock(chan); 00832 }
static void end_bridge_callback_data_fixup | ( | struct ast_bridge_config * | bconfig, | |
struct ast_channel * | originator, | |||
struct ast_channel * | terminator | |||
) | [static] |
Definition at line 834 of file app_dial.c.
References ast_bridge_config::end_bridge_callback_data.
Referenced by app_exec().
00834 { 00835 bconfig->end_bridge_callback_data = originator; 00836 }
static const char* get_cid_name | ( | char * | name, | |
int | namelen, | |||
struct ast_channel * | chan | |||
) | [static] |
Definition at line 387 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().
00388 { 00389 const char *context = S_OR(chan->macrocontext, chan->context); 00390 const char *exten = S_OR(chan->macroexten, chan->exten); 00391 00392 return ast_get_hint(NULL, 0, name, namelen, chan, context, exten) ? name : ""; 00393 }
static void hanguptree | ( | struct dial_localuser * | outgoing, | |
struct ast_channel * | exception | |||
) | [static] |
Definition at line 325 of file app_dial.c.
References ast_hangup(), dial_localuser::chan, free, and dial_localuser::next.
00326 { 00327 /* Hang up a tree of stuff */ 00328 struct dial_localuser *oo; 00329 while (outgoing) { 00330 /* Hangup any existing lines we have open */ 00331 if (outgoing->chan && (outgoing->chan != exception)) 00332 ast_hangup(outgoing->chan); 00333 oo = outgoing; 00334 outgoing=outgoing->next; 00335 free(oo); 00336 } 00337 }
static int load_module | ( | void | ) | [static] |
Definition at line 1935 of file app_dial.c.
References ast_register_application(), dial_exec(), and retrydial_exec().
01936 { 01937 int res; 01938 01939 res = ast_register_application(app, dial_exec, synopsis, descrip); 01940 res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip); 01941 01942 return res; 01943 }
static int onedigit_goto | ( | struct ast_channel * | chan, | |
const char * | context, | |||
char | exten, | |||
int | pri | |||
) | [static] |
Definition at line 368 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().
00369 { 00370 char rexten[2] = { exten, '\0' }; 00371 00372 if (context) { 00373 if (!ast_goto_if_exists(chan, context, rexten, pri)) 00374 return 1; 00375 } else { 00376 if (!ast_goto_if_exists(chan, chan->context, rexten, pri)) 00377 return 1; 00378 else if (!ast_strlen_zero(chan->macrocontext)) { 00379 if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri)) 00380 return 1; 00381 } 00382 } 00383 return 0; 00384 }
static void replace_macro_delimiter | ( | char * | s | ) | [static] |
static int retrydial_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 1807 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().
01808 { 01809 char *announce = NULL, *dialdata = NULL; 01810 const char *context = NULL; 01811 int sleep = 0, loops = 0, res = -1; 01812 struct ast_module_user *u; 01813 struct ast_flags peerflags; 01814 01815 if (ast_strlen_zero(data)) { 01816 ast_log(LOG_WARNING, "RetryDial requires an argument!\n"); 01817 return -1; 01818 } 01819 01820 u = ast_module_user_add(chan); 01821 01822 announce = ast_strdupa(data); 01823 01824 memset(&peerflags, 0, sizeof(peerflags)); 01825 01826 if ((dialdata = strchr(announce, '|'))) { 01827 *dialdata++ = '\0'; 01828 if (sscanf(dialdata, "%d", &sleep) == 1) { 01829 sleep *= 1000; 01830 } else { 01831 ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp); 01832 goto done; 01833 } 01834 if ((dialdata = strchr(dialdata, '|'))) { 01835 *dialdata++ = '\0'; 01836 if (sscanf(dialdata, "%d", &loops) != 1) { 01837 ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp); 01838 goto done; 01839 } 01840 } 01841 } 01842 01843 if ((dialdata = strchr(dialdata, '|'))) { 01844 *dialdata++ = '\0'; 01845 } else { 01846 ast_log(LOG_ERROR, "%s requires more arguments\n",rapp); 01847 goto done; 01848 } 01849 01850 if (sleep < 1000) 01851 sleep = 10000; 01852 01853 if (!loops) 01854 loops = -1; /* run forever */ 01855 01856 context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT"); 01857 01858 res = 0; 01859 while (loops) { 01860 int continue_exec; 01861 01862 chan->data = "Retrying"; 01863 if (ast_test_flag(chan, AST_FLAG_MOH)) 01864 ast_moh_stop(chan); 01865 01866 res = dial_exec_full(chan, dialdata, &peerflags, &continue_exec); 01867 if (continue_exec) 01868 break; 01869 01870 if (res == 0) { 01871 if (ast_test_flag(&peerflags, OPT_DTMF_EXIT)) { 01872 if (!ast_strlen_zero(announce)) { 01873 if (ast_fileexists(announce, NULL, chan->language) > 0) { 01874 if(!(res = ast_streamfile(chan, announce, chan->language))) 01875 ast_waitstream(chan, AST_DIGIT_ANY); 01876 } else 01877 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", announce); 01878 } 01879 if (!res && sleep) { 01880 if (!ast_test_flag(chan, AST_FLAG_MOH)) 01881 ast_moh_start(chan, NULL, NULL); 01882 res = ast_waitfordigit(chan, sleep); 01883 } 01884 } else { 01885 if (!ast_strlen_zero(announce)) { 01886 if (ast_fileexists(announce, NULL, chan->language) > 0) { 01887 if (!(res = ast_streamfile(chan, announce, chan->language))) 01888 res = ast_waitstream(chan, ""); 01889 } else 01890 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", announce); 01891 } 01892 if (sleep) { 01893 if (!ast_test_flag(chan, AST_FLAG_MOH)) 01894 ast_moh_start(chan, NULL, NULL); 01895 if (!res) 01896 res = ast_waitfordigit(chan, sleep); 01897 } 01898 } 01899 } 01900 01901 if (res < 0) 01902 break; 01903 else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */ 01904 if (onedigit_goto(chan, context, (char) res, 1)) { 01905 res = 0; 01906 break; 01907 } 01908 } 01909 loops--; 01910 } 01911 if (loops == 0) 01912 res = 0; 01913 else if (res == 1) 01914 res = 0; 01915 01916 if (ast_test_flag(chan, AST_FLAG_MOH)) 01917 ast_moh_stop(chan); 01918 done: 01919 ast_module_user_remove(u); 01920 return res; 01921 }
static void senddialevent | ( | struct ast_channel * | src, | |
struct ast_channel * | dst | |||
) | [static] |
Definition at line 395 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().
00396 { 00397 /* XXX do we need also CallerIDnum ? */ 00398 manager_event(EVENT_FLAG_CALL, "Dial", 00399 "Source: %s\r\n" 00400 "Destination: %s\r\n" 00401 "CallerID: %s\r\n" 00402 "CallerIDName: %s\r\n" 00403 "SrcUniqueID: %s\r\n" 00404 "DestUniqueID: %s\r\n", 00405 src->name, dst->name, S_OR(src->cid.cid_num, "<unknown>"), 00406 S_OR(src->cid.cid_name, "<unknown>"), src->uniqueid, 00407 dst->uniqueid); 00408 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1923 of file app_dial.c.
References ast_module_user_hangup_all, and ast_unregister_application().
01924 { 01925 int res; 01926 01927 res = ast_unregister_application(app); 01928 res |= ast_unregister_application(rapp); 01929 01930 ast_module_user_hangup_all(); 01931 01932 return res; 01933 }
static int valid_priv_reply | ( | struct ast_flags * | opts, | |
int | res | |||
) | [static] |
Definition at line 798 of file app_dial.c.
References ast_test_flag, OPT_PRIVACY, and OPT_SCREENING.
00799 { 00800 if (res < '1') 00801 return 0; 00802 if (ast_test_flag(opts, OPT_PRIVACY) && res <= '5') 00803 return 1; 00804 if (ast_test_flag(opts, OPT_SCREENING) && res <= '4') 00805 return 1; 00806 return 0; 00807 }
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 410 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, DIAL_NOFORWARDHTML, DIAL_STILLGOING, ast_channel::dialcontext, ast_cdr::disposition, ast_channel::exten, f, 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().
00411 { 00412 int numbusy = busystart; 00413 int numcongestion = congestionstart; 00414 int numnochan = nochanstart; 00415 int prestart = busystart + congestionstart + nochanstart; 00416 int orig = *to; 00417 struct ast_channel *peer = NULL; 00418 /* single is set if only one destination is enabled */ 00419 int single = outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK); 00420 00421 if (single) { 00422 /* Turn off hold music, etc */ 00423 ast_deactivate_generator(in); 00424 /* If we are calling a single channel, make them compatible for in-band tone purpose */ 00425 ast_channel_make_compatible(outgoing->chan, in); 00426 } 00427 00428 00429 while (*to && !peer) { 00430 struct dial_localuser *o; 00431 int pos = 0; /* how many channels do we handle */ 00432 int numlines = prestart; 00433 struct ast_channel *winner; 00434 struct ast_channel *watchers[AST_MAX_WATCHERS]; 00435 00436 watchers[pos++] = in; 00437 for (o = outgoing; o; o = o->next) { 00438 /* Keep track of important channels */ 00439 if (ast_test_flag(o, DIAL_STILLGOING) && o->chan) 00440 watchers[pos++] = o->chan; 00441 numlines++; 00442 } 00443 if (pos == 1) { /* only the input channel is available */ 00444 if (numlines == (numbusy + numcongestion + numnochan)) { 00445 if (option_verbose > 2) 00446 ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan); 00447 if (numbusy) 00448 strcpy(status, "BUSY"); 00449 else if (numcongestion) 00450 strcpy(status, "CONGESTION"); 00451 else if (numnochan) 00452 strcpy(status, "CHANUNAVAIL"); 00453 if (ast_opt_priority_jumping || priority_jump) 00454 ast_goto_if_exists(in, in->context, in->exten, in->priority + 101); 00455 } else { 00456 if (option_verbose > 2) 00457 ast_verbose(VERBOSE_PREFIX_3 "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan); 00458 } 00459 *to = 0; 00460 return NULL; 00461 } 00462 winner = ast_waitfor_n(watchers, pos, to); 00463 for (o = outgoing; o; o = o->next) { 00464 struct ast_frame *f; 00465 struct ast_channel *c = o->chan; 00466 00467 if (c == NULL) 00468 continue; 00469 if (ast_test_flag(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) { 00470 if (!peer) { 00471 if (option_verbose > 2) 00472 ast_verbose(VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name); 00473 peer = c; 00474 ast_copy_flags(peerflags, o, 00475 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 00476 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 00477 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 00478 OPT_CALLEE_PARK | OPT_CALLER_PARK | 00479 DIAL_NOFORWARDHTML); 00480 ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext)); 00481 ast_copy_string(c->exten, "", sizeof(c->exten)); 00482 } 00483 continue; 00484 } 00485 if (c != winner) 00486 continue; 00487 if (!ast_strlen_zero(c->call_forward)) { 00488 char tmpchan[256]; 00489 char *stuff; 00490 char *tech; 00491 int cause; 00492 00493 ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan)); 00494 if ((stuff = strchr(tmpchan, '/'))) { 00495 *stuff++ = '\0'; 00496 tech = tmpchan; 00497 } else { 00498 const char *forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT"); 00499 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context); 00500 stuff = tmpchan; 00501 tech = "Local"; 00502 } 00503 /* Before processing channel, go ahead and check for forwarding */ 00504 if (option_verbose > 2) 00505 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name); 00506 /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */ 00507 if (ast_test_flag(peerflags, OPT_IGNORE_FORWARDING)) { 00508 if (option_verbose > 2) 00509 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff); 00510 c = o->chan = NULL; 00511 cause = AST_CAUSE_BUSY; 00512 } else { 00513 /* Setup parameters */ 00514 if ((c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause))) { 00515 if (single) 00516 ast_channel_make_compatible(o->chan, in); 00517 ast_channel_inherit_variables(in, o->chan); 00518 ast_channel_datastore_inherit(in, o->chan); 00519 } else 00520 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause); 00521 } 00522 if (!c) { 00523 ast_clear_flag(o, DIAL_STILLGOING); 00524 HANDLE_CAUSE(cause, in); 00525 } else { 00526 ast_rtp_make_compatible(c, in, single); 00527 if (c->cid.cid_num) 00528 free(c->cid.cid_num); 00529 c->cid.cid_num = NULL; 00530 if (c->cid.cid_name) 00531 free(c->cid.cid_name); 00532 c->cid.cid_name = NULL; 00533 00534 if (ast_test_flag(o, OPT_FORCECLID)) { 00535 c->cid.cid_num = ast_strdup(S_OR(in->macroexten, in->exten)); 00536 ast_string_field_set(c, accountcode, winner->accountcode); 00537 c->cdrflags = winner->cdrflags; 00538 } else { 00539 c->cid.cid_num = ast_strdup(in->cid.cid_num); 00540 c->cid.cid_name = ast_strdup(in->cid.cid_name); 00541 ast_string_field_set(c, accountcode, in->accountcode); 00542 c->cdrflags = in->cdrflags; 00543 } 00544 00545 if (in->cid.cid_ani) { 00546 if (c->cid.cid_ani) 00547 free(c->cid.cid_ani); 00548 c->cid.cid_ani = ast_strdup(in->cid.cid_ani); 00549 } 00550 if (c->cid.cid_rdnis) 00551 free(c->cid.cid_rdnis); 00552 c->cid.cid_rdnis = ast_strdup(S_OR(in->macroexten, in->exten)); 00553 if (ast_call(c, tmpchan, 0)) { 00554 ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan); 00555 ast_clear_flag(o, DIAL_STILLGOING); 00556 ast_hangup(c); 00557 c = o->chan = NULL; 00558 numnochan++; 00559 } else { 00560 senddialevent(in, c); 00561 /* After calling, set callerid to extension */ 00562 if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID)) { 00563 char cidname[AST_MAX_EXTENSION] = ""; 00564 ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL); 00565 } 00566 } 00567 if (single) { 00568 ast_indicate(in, -1); 00569 } 00570 } 00571 /* Hangup the original channel now, in case we needed it */ 00572 ast_hangup(winner); 00573 continue; 00574 } 00575 f = ast_read(winner); 00576 if (!f) { 00577 in->hangupcause = c->hangupcause; 00578 ast_hangup(c); 00579 c = o->chan = NULL; 00580 ast_clear_flag(o, DIAL_STILLGOING); 00581 HANDLE_CAUSE(in->hangupcause, in); 00582 continue; 00583 } 00584 if (f->frametype == AST_FRAME_CONTROL) { 00585 switch(f->subclass) { 00586 case AST_CONTROL_ANSWER: 00587 /* This is our guy if someone answered. */ 00588 if (!peer) { 00589 if (option_verbose > 2) 00590 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name); 00591 peer = c; 00592 if (peer->cdr) { 00593 peer->cdr->answer = ast_tvnow(); 00594 peer->cdr->disposition = AST_CDR_ANSWERED; 00595 } 00596 ast_copy_flags(peerflags, o, 00597 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 00598 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 00599 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 00600 OPT_CALLEE_PARK | OPT_CALLER_PARK | 00601 DIAL_NOFORWARDHTML); 00602 ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext)); 00603 ast_copy_string(c->exten, "", sizeof(c->exten)); 00604 /* Setup RTP early bridge if appropriate */ 00605 if (CAN_EARLY_BRIDGE(peerflags, in, peer)) 00606 ast_rtp_early_bridge(in, peer); 00607 } 00608 /* If call has been answered, then the eventual hangup is likely to be normal hangup */ 00609 in->hangupcause = AST_CAUSE_NORMAL_CLEARING; 00610 c->hangupcause = AST_CAUSE_NORMAL_CLEARING; 00611 break; 00612 case AST_CONTROL_BUSY: 00613 if (option_verbose > 2) 00614 ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", c->name); 00615 in->hangupcause = c->hangupcause; 00616 ast_hangup(c); 00617 c = o->chan = NULL; 00618 ast_clear_flag(o, DIAL_STILLGOING); 00619 HANDLE_CAUSE(AST_CAUSE_BUSY, in); 00620 break; 00621 case AST_CONTROL_CONGESTION: 00622 if (option_verbose > 2) 00623 ast_verbose(VERBOSE_PREFIX_3 "%s is circuit-busy\n", c->name); 00624 in->hangupcause = c->hangupcause; 00625 ast_hangup(c); 00626 c = o->chan = NULL; 00627 ast_clear_flag(o, DIAL_STILLGOING); 00628 HANDLE_CAUSE(AST_CAUSE_CONGESTION, in); 00629 break; 00630 case AST_CONTROL_RINGING: 00631 if (option_verbose > 2) 00632 ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", c->name); 00633 /* Setup early media if appropriate */ 00634 if (single && CAN_EARLY_BRIDGE(peerflags, in, c)) 00635 ast_rtp_early_bridge(in, c); 00636 if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) { 00637 ast_indicate(in, AST_CONTROL_RINGING); 00638 (*sentringing)++; 00639 } 00640 break; 00641 case AST_CONTROL_PROGRESS: 00642 if (option_verbose > 2) 00643 ast_verbose (VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", c->name, in->name); 00644 /* Setup early media if appropriate */ 00645 if (single && CAN_EARLY_BRIDGE(peerflags, in, c)) 00646 ast_rtp_early_bridge(in, c); 00647 if (!ast_test_flag(outgoing, OPT_RINGBACK)) 00648 ast_indicate(in, AST_CONTROL_PROGRESS); 00649 break; 00650 case AST_CONTROL_VIDUPDATE: 00651 if (option_verbose > 2) 00652 ast_verbose (VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", c->name, in->name); 00653 ast_indicate(in, AST_CONTROL_VIDUPDATE); 00654 break; 00655 case AST_CONTROL_SRCUPDATE: 00656 if (option_verbose > 2) 00657 ast_verbose (VERBOSE_PREFIX_3 "%s requested a source update, passing it to %s\n", c->name, in->name); 00658 ast_indicate(in, AST_CONTROL_SRCUPDATE); 00659 break; 00660 case AST_CONTROL_PROCEEDING: 00661 if (option_verbose > 2) 00662 ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", c->name, in->name); 00663 if (single && CAN_EARLY_BRIDGE(peerflags, in, c)) 00664 ast_rtp_early_bridge(in, c); 00665 if (!ast_test_flag(outgoing, OPT_RINGBACK)) 00666 ast_indicate(in, AST_CONTROL_PROCEEDING); 00667 break; 00668 case AST_CONTROL_HOLD: 00669 if (option_verbose > 2) 00670 ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", c->name); 00671 ast_indicate(in, AST_CONTROL_HOLD); 00672 break; 00673 case AST_CONTROL_UNHOLD: 00674 if (option_verbose > 2) 00675 ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", c->name); 00676 ast_indicate(in, AST_CONTROL_UNHOLD); 00677 break; 00678 case AST_CONTROL_OFFHOOK: 00679 case AST_CONTROL_FLASH: 00680 /* Ignore going off hook and flash */ 00681 break; 00682 case -1: 00683 if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) { 00684 if (option_verbose > 2) 00685 ast_verbose(VERBOSE_PREFIX_3 "%s stopped sounds\n", c->name); 00686 ast_indicate(in, -1); 00687 (*sentringing) = 0; 00688 } 00689 break; 00690 default: 00691 if (option_debug) 00692 ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass); 00693 } 00694 } else if (single) { 00695 /* XXX are we sure the logic is correct ? or we should just switch on f->frametype ? */ 00696 if (f->frametype == AST_FRAME_VOICE && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) { 00697 if (ast_write(in, f)) 00698 ast_log(LOG_WARNING, "Unable to forward voice frame\n"); 00699 } else if (f->frametype == AST_FRAME_IMAGE && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) { 00700 if (ast_write(in, f)) 00701 ast_log(LOG_WARNING, "Unable to forward image\n"); 00702 } else if (f->frametype == AST_FRAME_TEXT && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) { 00703 if (ast_write(in, f)) 00704 ast_log(LOG_WARNING, "Unable to send text\n"); 00705 } else if (f->frametype == AST_FRAME_HTML && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) { 00706 if (ast_channel_sendhtml(in, f->subclass, f->data, f->datalen) == -1) 00707 ast_log(LOG_WARNING, "Unable to send URL\n"); 00708 } 00709 } 00710 ast_frfree(f); 00711 } /* end for */ 00712 if (winner == in) { 00713 struct ast_frame *f = ast_read(in); 00714 #if 0 00715 if (f && (f->frametype != AST_FRAME_VOICE)) 00716 printf("Frame type: %d, %d\n", f->frametype, f->subclass); 00717 else if (!f || (f->frametype != AST_FRAME_VOICE)) 00718 printf("Hangup received on %s\n", in->name); 00719 #endif 00720 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) { 00721 /* Got hung up */ 00722 *to = -1; 00723 ast_cdr_noanswer(in->cdr); 00724 strcpy(status, "CANCEL"); 00725 if (f) 00726 ast_frfree(f); 00727 return NULL; 00728 } 00729 00730 if (f && (f->frametype == AST_FRAME_DTMF)) { 00731 if (ast_test_flag(peerflags, OPT_DTMF_EXIT)) { 00732 const char *context = pbx_builtin_getvar_helper(in, "EXITCONTEXT"); 00733 if (onedigit_goto(in, context, (char) f->subclass, 1)) { 00734 if (option_verbose > 2) 00735 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass); 00736 *to=0; 00737 ast_cdr_noanswer(in->cdr); 00738 *result = f->subclass; 00739 strcpy(status, "CANCEL"); 00740 ast_frfree(f); 00741 return NULL; 00742 } 00743 } 00744 00745 if (ast_test_flag(peerflags, OPT_CALLER_HANGUP) && 00746 (f->subclass == '*')) { /* hmm it it not guaranteed to be '*' anymore. */ 00747 if (option_verbose > 2) 00748 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass); 00749 *to=0; 00750 ast_cdr_noanswer(in->cdr); 00751 strcpy(status, "CANCEL"); 00752 ast_frfree(f); 00753 return NULL; 00754 } 00755 } 00756 00757 /* Forward HTML stuff */ 00758 if (single && f && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) 00759 if(ast_channel_sendhtml(outgoing->chan, f->subclass, f->data, f->datalen) == -1) 00760 ast_log(LOG_WARNING, "Unable to send URL\n"); 00761 00762 00763 if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF_BEGIN) || (f->frametype == AST_FRAME_DTMF_END))) { 00764 if (ast_write(outgoing->chan, f)) 00765 ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n"); 00766 } 00767 if (single && (f->frametype == AST_FRAME_CONTROL) && 00768 ((f->subclass == AST_CONTROL_HOLD) || 00769 (f->subclass == AST_CONTROL_UNHOLD) || 00770 (f->subclass == AST_CONTROL_VIDUPDATE) || 00771 (f->subclass == AST_CONTROL_SRCUPDATE))) { 00772 if (option_verbose > 2) 00773 ast_verbose(VERBOSE_PREFIX_3 "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name); 00774 ast_indicate_data(outgoing->chan, f->subclass, f->data, f->datalen); 00775 } 00776 ast_frfree(f); 00777 } 00778 if (!*to && (option_verbose > 2)) 00779 ast_verbose(VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig); 00780 if (!*to || ast_check_hangup(in)) { 00781 ast_cdr_noanswer(in->cdr); 00782 } 00783 00784 } 00785 00786 return peer; 00787 }
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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 1945 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 1945 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 }, [ '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 307 of file app_dial.c.
char* rapp = "RetryDial" [static] |
Definition at line 215 of file app_dial.c.
char* rdescrip [static] |
Definition at line 217 of file app_dial.c.
char* rsynopsis = "Place a call, retrying on failure allowing optional exit extension." [static] |
Definition at line 216 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.