#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"
Include dependency graph for app_dial.c:

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 | |
| AST_APP_OPTIONS (dial_exec_options,{AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE), AST_APP_OPTION('C', OPT_RESETCDR), AST_APP_OPTION('d', OPT_DTMF_EXIT), AST_APP_OPTION_ARG('D', OPT_SENDDTMF, OPT_ARG_SENDDTMF), AST_APP_OPTION('f', OPT_FORCECLID), AST_APP_OPTION('g', OPT_GO_ON), AST_APP_OPTION_ARG('G', OPT_GOTO, OPT_ARG_GOTO), AST_APP_OPTION('h', OPT_CALLEE_HANGUP), AST_APP_OPTION('H', OPT_CALLER_HANGUP), AST_APP_OPTION('i', OPT_IGNORE_FORWARDING), AST_APP_OPTION('j', OPT_PRIORITY_JUMP), AST_APP_OPTION('k', OPT_CALLEE_PARK), AST_APP_OPTION('K', OPT_CALLER_PARK), AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT), AST_APP_OPTION_ARG('m', OPT_MUSICBACK, OPT_ARG_MUSICBACK), AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO), AST_APP_OPTION('n', OPT_SCREEN_NOINTRO), AST_APP_OPTION('N', OPT_SCREEN_NOCLID), AST_APP_OPTION('o', OPT_ORIGINAL_CLID), AST_APP_OPTION_ARG('O', OPT_OPERMODE, OPT_ARG_OPERMODE), AST_APP_OPTION('p', OPT_SCREENING), AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY), AST_APP_OPTION('r', OPT_RINGBACK), AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP), AST_APP_OPTION('t', OPT_CALLEE_TRANSFER), AST_APP_OPTION('T', OPT_CALLER_TRANSFER), AST_APP_OPTION('w', OPT_CALLEE_MONITOR), AST_APP_OPTION('W', OPT_CALLER_MONITOR),}) | |
| AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Dialing Application") | |
| static int | dial_exec (struct ast_channel *chan, void *data) |
| 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 void | set_dial_features (struct ast_flags *opts, struct ast_dial_features *features) |
| 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 char * | app = "Dial" |
| static char * | descrip |
| enum { ... } | dial_exec_option_args |
| enum { ... } | dial_exec_option_flags |
| 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 331 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 301 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 222 of file app_dial.c.
00222 { 00223 OPT_ANNOUNCE = (1 << 0), 00224 OPT_RESETCDR = (1 << 1), 00225 OPT_DTMF_EXIT = (1 << 2), 00226 OPT_SENDDTMF = (1 << 3), 00227 OPT_FORCECLID = (1 << 4), 00228 OPT_GO_ON = (1 << 5), 00229 OPT_CALLEE_HANGUP = (1 << 6), 00230 OPT_CALLER_HANGUP = (1 << 7), 00231 OPT_PRIORITY_JUMP = (1 << 8), 00232 OPT_DURATION_LIMIT = (1 << 9), 00233 OPT_MUSICBACK = (1 << 10), 00234 OPT_CALLEE_MACRO = (1 << 11), 00235 OPT_SCREEN_NOINTRO = (1 << 12), 00236 OPT_SCREEN_NOCLID = (1 << 13), 00237 OPT_ORIGINAL_CLID = (1 << 14), 00238 OPT_SCREENING = (1 << 15), 00239 OPT_PRIVACY = (1 << 16), 00240 OPT_RINGBACK = (1 << 17), 00241 OPT_DURATION_STOP = (1 << 18), 00242 OPT_CALLEE_TRANSFER = (1 << 19), 00243 OPT_CALLER_TRANSFER = (1 << 20), 00244 OPT_CALLEE_MONITOR = (1 << 21), 00245 OPT_CALLER_MONITOR = (1 << 22), 00246 OPT_GOTO = (1 << 23), 00247 OPT_OPERMODE = (1 << 24), 00248 OPT_CALLEE_PARK = (1 << 25), 00249 OPT_CALLER_PARK = (1 << 26), 00250 OPT_IGNORE_FORWARDING = (1 << 27), 00251 } 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 256 of file app_dial.c.
00256 { 00257 OPT_ARG_ANNOUNCE = 0, 00258 OPT_ARG_SENDDTMF, 00259 OPT_ARG_GOTO, 00260 OPT_ARG_DURATION_LIMIT, 00261 OPT_ARG_MUSICBACK, 00262 OPT_ARG_CALLEE_MACRO, 00263 OPT_ARG_PRIVACY, 00264 OPT_ARG_DURATION_STOP, 00265 OPT_ARG_OPERMODE, 00266 /* note: this entry _MUST_ be the last one in the enum */ 00267 OPT_ARG_ARRAY_SIZE, 00268 } dial_exec_option_args;
| AST_APP_OPTIONS | ( | dial_exec_options | ) |
| AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
| "Dialing Application" | ||||
| ) |
| static int dial_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 1828 of file app_dial.c.
Referenced by load_module().
01829 { 01830 struct ast_flags peerflags; 01831 01832 memset(&peerflags, 0, sizeof(peerflags)); 01833 01834 return dial_exec_full(chan, data, &peerflags, NULL); 01835 }
| static const char* get_cid_name | ( | char * | name, | |
| int | namelen, | |||
| struct ast_channel * | chan | |||
| ) | [static] |
Definition at line 379 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().
00380 { 00381 const char *context = S_OR(chan->macrocontext, chan->context); 00382 const char *exten = S_OR(chan->macroexten, chan->exten); 00383 00384 return ast_get_hint(NULL, 0, name, namelen, chan, context, exten) ? name : ""; 00385 }
| static void hanguptree | ( | struct dial_localuser * | outgoing, | |
| struct ast_channel * | exception | |||
| ) | [static] |
Definition at line 317 of file app_dial.c.
References ast_hangup(), dial_localuser::chan, free, and dial_localuser::next.
00318 { 00319 /* Hang up a tree of stuff */ 00320 struct dial_localuser *oo; 00321 while (outgoing) { 00322 /* Hangup any existing lines we have open */ 00323 if (outgoing->chan && (outgoing->chan != exception)) 00324 ast_hangup(outgoing->chan); 00325 oo = outgoing; 00326 outgoing=outgoing->next; 00327 free(oo); 00328 } 00329 }
| static int load_module | ( | void | ) | [static] |
Definition at line 1965 of file app_dial.c.
References ast_register_application(), dial_exec(), and retrydial_exec().
01966 { 01967 int res; 01968 01969 res = ast_register_application(app, dial_exec, synopsis, descrip); 01970 res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip); 01971 01972 return res; 01973 }
| static int onedigit_goto | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| char | exten, | |||
| int | pri | |||
| ) | [static] |
Definition at line 360 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().
00361 { 00362 char rexten[2] = { exten, '\0' }; 00363 00364 if (context) { 00365 if (!ast_goto_if_exists(chan, context, rexten, pri)) 00366 return 1; 00367 } else { 00368 if (!ast_goto_if_exists(chan, chan->context, rexten, pri)) 00369 return 1; 00370 else if (!ast_strlen_zero(chan->macrocontext)) { 00371 if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri)) 00372 return 1; 00373 } 00374 } 00375 return 0; 00376 }
| static void replace_macro_delimiter | ( | char * | s | ) | [static] |
| static int retrydial_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 1837 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().
01838 { 01839 char *announce = NULL, *dialdata = NULL; 01840 const char *context = NULL; 01841 int sleep = 0, loops = 0, res = -1; 01842 struct ast_module_user *u; 01843 struct ast_flags peerflags; 01844 01845 if (ast_strlen_zero(data)) { 01846 ast_log(LOG_WARNING, "RetryDial requires an argument!\n"); 01847 return -1; 01848 } 01849 01850 u = ast_module_user_add(chan); 01851 01852 announce = ast_strdupa(data); 01853 01854 memset(&peerflags, 0, sizeof(peerflags)); 01855 01856 if ((dialdata = strchr(announce, '|'))) { 01857 *dialdata++ = '\0'; 01858 if (sscanf(dialdata, "%d", &sleep) == 1) { 01859 sleep *= 1000; 01860 } else { 01861 ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp); 01862 goto done; 01863 } 01864 if ((dialdata = strchr(dialdata, '|'))) { 01865 *dialdata++ = '\0'; 01866 if (sscanf(dialdata, "%d", &loops) != 1) { 01867 ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp); 01868 goto done; 01869 } 01870 } 01871 } 01872 01873 if ((dialdata = strchr(dialdata, '|'))) { 01874 *dialdata++ = '\0'; 01875 } else { 01876 ast_log(LOG_ERROR, "%s requires more arguments\n",rapp); 01877 goto done; 01878 } 01879 01880 if (sleep < 1000) 01881 sleep = 10000; 01882 01883 if (!loops) 01884 loops = -1; /* run forever */ 01885 01886 context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT"); 01887 01888 res = 0; 01889 while (loops) { 01890 int continue_exec; 01891 01892 chan->data = "Retrying"; 01893 if (ast_test_flag(chan, AST_FLAG_MOH)) 01894 ast_moh_stop(chan); 01895 01896 res = dial_exec_full(chan, dialdata, &peerflags, &continue_exec); 01897 if (continue_exec) 01898 break; 01899 01900 if (res == 0) { 01901 if (ast_test_flag(&peerflags, OPT_DTMF_EXIT)) { 01902 if (!ast_strlen_zero(announce)) { 01903 if (ast_fileexists(announce, NULL, chan->language) > 0) { 01904 if(!(res = ast_streamfile(chan, announce, chan->language))) 01905 ast_waitstream(chan, AST_DIGIT_ANY); 01906 } else 01907 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", announce); 01908 } 01909 if (!res && sleep) { 01910 if (!ast_test_flag(chan, AST_FLAG_MOH)) 01911 ast_moh_start(chan, NULL, NULL); 01912 res = ast_waitfordigit(chan, sleep); 01913 } 01914 } else { 01915 if (!ast_strlen_zero(announce)) { 01916 if (ast_fileexists(announce, NULL, chan->language) > 0) { 01917 if (!(res = ast_streamfile(chan, announce, chan->language))) 01918 res = ast_waitstream(chan, ""); 01919 } else 01920 ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", announce); 01921 } 01922 if (sleep) { 01923 if (!ast_test_flag(chan, AST_FLAG_MOH)) 01924 ast_moh_start(chan, NULL, NULL); 01925 if (!res) 01926 res = ast_waitfordigit(chan, sleep); 01927 } 01928 } 01929 } 01930 01931 if (res < 0) 01932 break; 01933 else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */ 01934 if (onedigit_goto(chan, context, (char) res, 1)) { 01935 res = 0; 01936 break; 01937 } 01938 } 01939 loops--; 01940 } 01941 if (loops == 0) 01942 res = 0; 01943 else if (res == 1) 01944 res = 0; 01945 01946 if (ast_test_flag(chan, AST_FLAG_MOH)) 01947 ast_moh_stop(chan); 01948 done: 01949 ast_module_user_remove(u); 01950 return res; 01951 }
| static void senddialevent | ( | struct ast_channel * | src, | |
| struct ast_channel * | dst | |||
| ) | [static] |
Definition at line 387 of file app_dial.c.
References ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, EVENT_FLAG_CALL, manager_event(), and S_OR.
Referenced by wait_for_answer().
00388 { 00389 /* XXX do we need also CallerIDnum ? */ 00390 manager_event(EVENT_FLAG_CALL, "Dial", 00391 "Source: %s\r\n" 00392 "Destination: %s\r\n" 00393 "CallerID: %s\r\n" 00394 "CallerIDName: %s\r\n" 00395 "SrcUniqueID: %s\r\n" 00396 "DestUniqueID: %s\r\n", 00397 src->name, dst->name, S_OR(src->cid.cid_num, "<unknown>"), 00398 S_OR(src->cid.cid_name, "<unknown>"), src->uniqueid, 00399 dst->uniqueid); 00400 }
| static void set_dial_features | ( | struct ast_flags * | opts, | |
| struct ast_dial_features * | features | |||
| ) | [static] |
Definition at line 798 of file app_dial.c.
References ast_app_options2str(), ast_copy_flags, AST_FEATURE_AUTOMON, AST_FEATURE_DISCONNECT, AST_FEATURE_PARKCALL, AST_FEATURE_REDIRECT, ast_set_flag, ast_test_flag, ast_dial_features::features_callee, ast_dial_features::features_caller, ast_flags::flags, OPT_CALLEE_HANGUP, OPT_CALLEE_MONITOR, OPT_CALLEE_PARK, OPT_CALLEE_TRANSFER, OPT_CALLER_HANGUP, OPT_CALLER_MONITOR, OPT_CALLER_PARK, OPT_CALLER_TRANSFER, and ast_dial_features::options.
00799 { 00800 struct ast_flags perm_opts = {.flags = 0}; 00801 00802 ast_copy_flags(&perm_opts, opts, 00803 OPT_CALLER_TRANSFER | OPT_CALLER_PARK | OPT_CALLER_MONITOR | OPT_CALLER_HANGUP | 00804 OPT_CALLEE_TRANSFER | OPT_CALLEE_PARK | OPT_CALLEE_MONITOR | OPT_CALLEE_HANGUP); 00805 00806 memset(features->options, 0, sizeof(features->options)); 00807 00808 ast_app_options2str(dial_exec_options, &perm_opts, features->options, sizeof(features->options)); 00809 if (ast_test_flag(&perm_opts, OPT_CALLEE_TRANSFER)) 00810 ast_set_flag(&(features->features_callee), AST_FEATURE_REDIRECT); 00811 if (ast_test_flag(&perm_opts, OPT_CALLER_TRANSFER)) 00812 ast_set_flag(&(features->features_caller), AST_FEATURE_REDIRECT); 00813 if (ast_test_flag(&perm_opts, OPT_CALLEE_HANGUP)) 00814 ast_set_flag(&(features->features_callee), AST_FEATURE_DISCONNECT); 00815 if (ast_test_flag(&perm_opts, OPT_CALLER_HANGUP)) 00816 ast_set_flag(&(features->features_caller), AST_FEATURE_DISCONNECT); 00817 if (ast_test_flag(&perm_opts, OPT_CALLEE_MONITOR)) 00818 ast_set_flag(&(features->features_callee), AST_FEATURE_AUTOMON); 00819 if (ast_test_flag(&perm_opts, OPT_CALLER_MONITOR)) 00820 ast_set_flag(&(features->features_caller), AST_FEATURE_AUTOMON); 00821 if (ast_test_flag(&perm_opts, OPT_CALLEE_PARK)) 00822 ast_set_flag(&(features->features_callee), AST_FEATURE_PARKCALL); 00823 if (ast_test_flag(&perm_opts, OPT_CALLER_PARK)) 00824 ast_set_flag(&(features->features_caller), AST_FEATURE_PARKCALL); 00825 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 1953 of file app_dial.c.
References ast_module_user_hangup_all, and ast_unregister_application().
01954 { 01955 int res; 01956 01957 res = ast_unregister_application(app); 01958 res |= ast_unregister_application(rapp); 01959 01960 ast_module_user_hangup_all(); 01961 01962 return res; 01963 }
| static int valid_priv_reply | ( | struct ast_flags * | opts, | |
| int | res | |||
| ) | [static] |
Definition at line 787 of file app_dial.c.
References ast_test_flag, OPT_PRIVACY, and OPT_SCREENING.
00788 { 00789 if (res < '1') 00790 return 0; 00791 if (ast_test_flag(opts, OPT_PRIVACY) && res <= '5') 00792 return 1; 00793 if (ast_test_flag(opts, OPT_SCREENING) && res <= '4') 00794 return 1; 00795 return 0; 00796 }
| 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 402 of file app_dial.c.
References ast_channel::_state, 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_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_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::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().
00403 { 00404 int numbusy = busystart; 00405 int numcongestion = congestionstart; 00406 int numnochan = nochanstart; 00407 int prestart = busystart + congestionstart + nochanstart; 00408 int orig = *to; 00409 struct ast_channel *peer = NULL; 00410 /* single is set if only one destination is enabled */ 00411 int single = outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK); 00412 00413 if (single) { 00414 /* Turn off hold music, etc */ 00415 ast_deactivate_generator(in); 00416 /* If we are calling a single channel, make them compatible for in-band tone purpose */ 00417 ast_channel_make_compatible(outgoing->chan, in); 00418 } 00419 00420 00421 while (*to && !peer) { 00422 struct dial_localuser *o; 00423 int pos = 0; /* how many channels do we handle */ 00424 int numlines = prestart; 00425 struct ast_channel *winner; 00426 struct ast_channel *watchers[AST_MAX_WATCHERS]; 00427 00428 watchers[pos++] = in; 00429 for (o = outgoing; o; o = o->next) { 00430 /* Keep track of important channels */ 00431 if (ast_test_flag(o, DIAL_STILLGOING) && o->chan) 00432 watchers[pos++] = o->chan; 00433 numlines++; 00434 } 00435 if (pos == 1) { /* only the input channel is available */ 00436 if (numlines == (numbusy + numcongestion + numnochan)) { 00437 if (option_verbose > 2) 00438 ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan); 00439 if (numbusy) 00440 strcpy(status, "BUSY"); 00441 else if (numcongestion) 00442 strcpy(status, "CONGESTION"); 00443 else if (numnochan) 00444 strcpy(status, "CHANUNAVAIL"); 00445 if (ast_opt_priority_jumping || priority_jump) 00446 ast_goto_if_exists(in, in->context, in->exten, in->priority + 101); 00447 } else { 00448 if (option_verbose > 2) 00449 ast_verbose(VERBOSE_PREFIX_3 "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan); 00450 } 00451 *to = 0; 00452 return NULL; 00453 } 00454 winner = ast_waitfor_n(watchers, pos, to); 00455 for (o = outgoing; o; o = o->next) { 00456 struct ast_frame *f; 00457 struct ast_channel *c = o->chan; 00458 00459 if (c == NULL) 00460 continue; 00461 if (ast_test_flag(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) { 00462 if (!peer) { 00463 if (option_verbose > 2) 00464 ast_verbose(VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name); 00465 peer = c; 00466 ast_copy_flags(peerflags, o, 00467 OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | 00468 OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | 00469 OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | 00470 OPT_CALLEE_PARK | OPT_CALLER_PARK | 00471 DIAL_NOFORWARDHTML); 00472 ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext)); 00473 ast_copy_string(c->exten, "", sizeof(c->exten)); 00474 } 00475 continue; 00476 } 00477 if (c != winner) 00478 continue; 00479 if (!ast_strlen_zero(c->call_forward)) { 00480 char tmpchan[256]; 00481 char *stuff; 00482 char *tech; 00483 int cause; 00484 00485 ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan)); 00486 if ((stuff = strchr(tmpchan, '/'))) { 00487 *stuff++ = '\0'; 00488 tech = tmpchan; 00489 } else { 00490 const char *forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT"); 00491 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context); 00492 stuff = tmpchan; 00493 tech = "Local"; 00494 } 00495 /* Before processing channel, go ahead and check for forwarding */ 00496 if (option_verbose > 2) 00497 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name); 00498 /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */ 00499 if (ast_test_flag(peerflags, OPT_IGNORE_FORWARDING)) { 00500 if (option_verbose > 2) 00501 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff); 00502 c = o->chan = NULL; 00503 cause = AST_CAUSE_BUSY; 00504 } else { 00505 /* Setup parameters */ 00506