#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/linkedlists.h"
#include "asterisk/dial.h"
#include "asterisk/pbx.h"
#include "asterisk/musiconhold.h"
Go to the source code of this file.
Data Structures | |
struct | answer_exec_struct |
Structure for 'ANSWER_EXEC' option. More... | |
struct | ast_dial |
Main dialing structure. Contains global options, channels being dialed, and more! More... | |
struct | ast_dial_channel |
Dialing channel structure. Contains per-channel dialing options, asterisk channel, and more! More... | |
struct | ast_option_types |
Options structure - maps options to respective handlers (enable/disable). This list MUST be perfectly kept in order, or else madness will happen. More... | |
Defines | |
#define | AST_MAX_WATCHERS 256 |
Maximum number of channels we can watch at a time. | |
#define | FIND_RELATIVE_OPTION(dial, dial_channel, ast_dial_option) (dial_channel->options[ast_dial_option] ? dial_channel->options[ast_dial_option] : dial->options[ast_dial_option]) |
Macro for finding the option structure to use on a dialed channel. | |
#define | IS_CALLER(chan, owner) (chan == owner ? 1 : 0) |
Macro that determines whether a channel is the caller or not. | |
#define | S_REPLACE(s, new_val) |
free the buffer if allocated, and set the pointer to the second arg | |
Typedefs | |
typedef int(*) | ast_dial_option_cb_disable (void *data) |
Typedef for dial option disable. | |
typedef void *(*) | ast_dial_option_cb_enable (void *data) |
Typedef for dial option enable. | |
Functions | |
static int | answer_exec_disable (void *data) |
Disable function for 'ANSWER_EXEC' option. | |
static void * | answer_exec_enable (void *data) |
Enable function for 'ANSWER_EXEC' option. | |
static void | answer_exec_run (struct ast_dial *dial, struct ast_dial_channel *dial_channel, char *app, char *args) |
Application execution function for 'ANSWER_EXEC' option. | |
ast_channel * | ast_dial_answered (struct ast_dial *dial) |
Return channel that answered. | |
ast_channel * | ast_dial_answered_steal (struct ast_dial *dial) |
Steal the channel that answered. | |
int | ast_dial_append (struct ast_dial *dial, const char *tech, const char *device) |
Append a channel. | |
ast_dial * | ast_dial_create (void) |
New dialing structure. | |
int | ast_dial_destroy (struct ast_dial *dial) |
Destroys a dialing structure. | |
void | ast_dial_hangup (struct ast_dial *dial) |
Hangup channels. | |
enum ast_dial_result | ast_dial_join (struct ast_dial *dial) |
Cancel async thread. | |
int | ast_dial_option_disable (struct ast_dial *dial, int num, enum ast_dial_option option) |
Disables an option per channel. | |
int | ast_dial_option_enable (struct ast_dial *dial, int num, enum ast_dial_option option, void *data) |
Enables an option per channel. | |
int | ast_dial_option_global_disable (struct ast_dial *dial, enum ast_dial_option option) |
Disables an option globally. | |
int | ast_dial_option_global_enable (struct ast_dial *dial, enum ast_dial_option option, void *data) |
Enables an option globally. | |
enum ast_dial_result | ast_dial_run (struct ast_dial *dial, struct ast_channel *chan, int async) |
Execute dialing synchronously or asynchronously. | |
void | ast_dial_set_global_timeout (struct ast_dial *dial, int timeout) |
Set the maximum time (globally) allowed for trying to ring phones. | |
void | ast_dial_set_state_callback (struct ast_dial *dial, ast_dial_state_callback callback) |
Set a callback for state changes. | |
void | ast_dial_set_timeout (struct ast_dial *dial, int num, int timeout) |
Set the maximum time (per channel) allowed for trying to ring the phone. | |
enum ast_dial_result | ast_dial_state (struct ast_dial *dial) |
Return state of dial. | |
static void * | async_dial (void *data) |
Dial async thread function. | |
static int | begin_dial (struct ast_dial *dial, struct ast_channel *chan) |
Helper function that does the beginning dialing per dial structure. | |
static int | begin_dial_channel (struct ast_dial_channel *channel, struct ast_channel *chan) |
Helper function that does the beginning dialing per-appended channel. | |
static struct ast_dial_channel * | find_dial_channel (struct ast_dial *dial, int num) |
Helper function for finding a channel in a dial structure based on number. | |
static struct ast_dial_channel * | find_relative_dial_channel (struct ast_dial *dial, struct ast_channel *owner) |
Helper function that finds the dialed channel based on owner. | |
static int | handle_call_forward (struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_channel *chan) |
Helper function to handle channels that have been call forwarded. | |
static void | handle_frame (struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr, struct ast_channel *chan) |
Helper function that handles control frames WITH owner. | |
static void | handle_frame_ownerless (struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr) |
Helper function that handles control frames WITHOUT owner. | |
static int | handle_timeout_trip (struct ast_dial *dial, struct timeval start) |
Helper function to handle when a timeout occurs on dialing attempt. | |
static enum ast_dial_result | monitor_dial (struct ast_dial *dial, struct ast_channel *chan) |
Helper function that basically keeps tabs on dialing attempts. | |
static int | music_disable (void *data) |
static void * | music_enable (void *data) |
static void | set_state (struct ast_dial *dial, enum ast_dial_result state) |
Variables | |
static struct ast_option_types | option_types [] |
Options structure - maps options to respective handlers (enable/disable). This list MUST be perfectly kept in order, or else madness will happen. |
Definition in file dial.c.
#define AST_MAX_WATCHERS 256 |
Maximum number of channels we can watch at a time.
Definition at line 186 of file dial.c.
Referenced by monitor_dial(), and wait_for_answer().
#define FIND_RELATIVE_OPTION | ( | dial, | |||
dial_channel, | |||||
ast_dial_option | ) | (dial_channel->options[ast_dial_option] ? dial_channel->options[ast_dial_option] : dial->options[ast_dial_option]) |
Macro for finding the option structure to use on a dialed channel.
Definition at line 189 of file dial.c.
Referenced by handle_call_forward(), and monitor_dial().
Macro that determines whether a channel is the caller or not.
Definition at line 192 of file dial.c.
Referenced by monitor_dial().
#define S_REPLACE | ( | s, | |||
new_val | ) |
free the buffer if allocated, and set the pointer to the second arg
Definition at line 177 of file dial.c.
Referenced by begin_dial_channel(), dial_exec_full(), and do_forward().
typedef int(*) ast_dial_option_cb_disable(void *data) |
typedef void*(*) ast_dial_option_cb_enable(void *data) |
static int answer_exec_disable | ( | void * | data | ) | [static] |
Disable function for 'ANSWER_EXEC' option.
Definition at line 106 of file dial.c.
References answer_exec_struct::args, and ast_free.
00107 { 00108 struct answer_exec_struct *answer_exec = data; 00109 00110 /* Make sure we have a value */ 00111 if (!answer_exec) 00112 return -1; 00113 00114 /* If arguments are present, free them too */ 00115 if (answer_exec->args) 00116 ast_free(answer_exec->args); 00117 00118 /* This is simple - just free the structure */ 00119 ast_free(answer_exec); 00120 00121 return 0; 00122 }
static void* answer_exec_enable | ( | void * | data | ) | [static] |
Enable function for 'ANSWER_EXEC' option.
Definition at line 80 of file dial.c.
References app, answer_exec_struct::args, ast_calloc, ast_copy_string(), ast_strdup, ast_strdupa, and ast_strlen_zero().
00081 { 00082 struct answer_exec_struct *answer_exec = NULL; 00083 char *app = ast_strdupa((char*)data), *args = NULL; 00084 00085 /* Not giving any data to this option is bad, mmmk? */ 00086 if (ast_strlen_zero(app)) 00087 return NULL; 00088 00089 /* Create new data structure */ 00090 if (!(answer_exec = ast_calloc(1, sizeof(*answer_exec)))) 00091 return NULL; 00092 00093 /* Parse out application and arguments */ 00094 if ((args = strchr(app, ','))) { 00095 *args++ = '\0'; 00096 answer_exec->args = ast_strdup(args); 00097 } 00098 00099 /* Copy application name */ 00100 ast_copy_string(answer_exec->app, app, sizeof(answer_exec->app)); 00101 00102 return answer_exec; 00103 }
static void answer_exec_run | ( | struct ast_dial * | dial, | |
struct ast_dial_channel * | dial_channel, | |||
char * | app, | |||
char * | args | |||
) | [static] |
Application execution function for 'ANSWER_EXEC' option.
Definition at line 140 of file dial.c.
References ast_hangup(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_STOP, chan, ast_dial::lock, ast_dial_channel::owner, pbx_exec(), pbx_findapp(), and ast_dial::thread.
Referenced by monitor_dial().
00141 { 00142 struct ast_channel *chan = dial_channel->owner; 00143 struct ast_app *ast_app = pbx_findapp(app); 00144 00145 /* If the application was not found, return immediately */ 00146 if (!ast_app) 00147 return; 00148 00149 /* All is well... execute the application */ 00150 pbx_exec(chan, ast_app, args); 00151 00152 /* If another thread is not taking over hang up the channel */ 00153 ast_mutex_lock(&dial->lock); 00154 if (dial->thread != AST_PTHREADT_STOP) { 00155 ast_hangup(chan); 00156 dial_channel->owner = NULL; 00157 } 00158 ast_mutex_unlock(&dial->lock); 00159 00160 return; 00161 }
struct ast_channel* ast_dial_answered | ( | struct ast_dial * | dial | ) |
Return channel that answered.
dial | Dialing structure |
Definition at line 737 of file dial.c.
References AST_DIAL_RESULT_ANSWERED, AST_LIST_FIRST, ast_dial::channels, and ast_dial::state.
Referenced by dial_trunk(), and sla_handle_dial_state_event().
00738 { 00739 if (!dial) 00740 return NULL; 00741 00742 return ((dial->state == AST_DIAL_RESULT_ANSWERED) ? AST_LIST_FIRST(&dial->channels)->owner : NULL); 00743 }
struct ast_channel* ast_dial_answered_steal | ( | struct ast_dial * | dial | ) |
Steal the channel that answered.
dial | Dialing structure |
Definition at line 749 of file dial.c.
References AST_DIAL_RESULT_ANSWERED, AST_LIST_FIRST, chan, ast_dial::channels, and ast_dial::state.
00750 { 00751 struct ast_channel *chan = NULL; 00752 00753 if (!dial) 00754 return NULL; 00755 00756 if (dial->state == AST_DIAL_RESULT_ANSWERED) { 00757 chan = AST_LIST_FIRST(&dial->channels)->owner; 00758 AST_LIST_FIRST(&dial->channels)->owner = NULL; 00759 } 00760 00761 return chan; 00762 }
int ast_dial_append | ( | struct ast_dial * | dial, | |
const char * | tech, | |||
const char * | device | |||
) |
Append a channel.
Definition at line 226 of file dial.c.
References ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_TAIL, ast_strdup, ast_dial::channels, ast_dial_channel::list, and ast_dial::num.
Referenced by dial_trunk(), page_exec(), and sla_ring_station().
00227 { 00228 struct ast_dial_channel *channel = NULL; 00229 00230 /* Make sure we have required arguments */ 00231 if (!dial || !tech || !device) 00232 return -1; 00233 00234 /* Allocate new memory for dialed channel structure */ 00235 if (!(channel = ast_calloc(1, sizeof(*channel)))) 00236 return -1; 00237 00238 /* Record technology and device for when we actually dial */ 00239 channel->tech = ast_strdup(tech); 00240 channel->device = ast_strdup(device); 00241 00242 /* Grab reference number from dial structure */ 00243 channel->num = ast_atomic_fetchadd_int(&dial->num, +1); 00244 00245 /* No timeout exists... yet */ 00246 channel->timeout = -1; 00247 00248 /* Insert into channels list */ 00249 AST_LIST_INSERT_TAIL(&dial->channels, channel, list); 00250 00251 return channel->num; 00252 }
struct ast_dial* ast_dial_create | ( | void | ) |
New dialing structure.
Definition at line 198 of file dial.c.
References ast_calloc, AST_LIST_HEAD_INIT, ast_mutex_init(), and AST_PTHREADT_NULL.
Referenced by dial_trunk(), page_exec(), and sla_ring_station().
00199 { 00200 struct ast_dial *dial = NULL; 00201 00202 /* Allocate new memory for structure */ 00203 if (!(dial = ast_calloc(1, sizeof(*dial)))) 00204 return NULL; 00205 00206 /* Initialize list of channels */ 00207 AST_LIST_HEAD_INIT(&dial->channels); 00208 00209 /* Initialize thread to NULL */ 00210 dial->thread = AST_PTHREADT_NULL; 00211 00212 /* No timeout exists... yet */ 00213 dial->timeout = -1; 00214 dial->actual_timeout = -1; 00215 00216 /* Can't forget about the lock */ 00217 ast_mutex_init(&dial->lock); 00218 00219 return dial; 00220 }
int ast_dial_destroy | ( | struct ast_dial * | dial | ) |
Destroys a dialing structure.
dial | Dialing structure to free |
Definition at line 849 of file dial.c.
References AST_DIAL_OPTION_MAX, ast_free, ast_hangup(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, ast_dial::channels, ast_dial_channel::device, ast_dial_channel::list, option_types, ast_dial_channel::options, ast_dial_channel::owner, and ast_dial_channel::tech.
Referenced by dial_trunk(), page_exec(), run_station(), sla_hangup_stations(), sla_ring_station(), and sla_stop_ringing_station().
00850 { 00851 int i = 0; 00852 struct ast_dial_channel *channel = NULL; 00853 00854 if (!dial) 00855 return -1; 00856 00857 /* Hangup and deallocate all the dialed channels */ 00858 AST_LIST_LOCK(&dial->channels); 00859 AST_LIST_TRAVERSE_SAFE_BEGIN(&dial->channels, channel, list) { 00860 /* Disable any enabled options */ 00861 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) { 00862 if (!channel->options[i]) 00863 continue; 00864 if (option_types[i].disable) 00865 option_types[i].disable(channel->options[i]); 00866 channel->options[i] = NULL; 00867 } 00868 /* Hang up channel if need be */ 00869 if (channel->owner) { 00870 ast_hangup(channel->owner); 00871 channel->owner = NULL; 00872 } 00873 /* Free structure */ 00874 ast_free(channel->tech); 00875 ast_free(channel->device); 00876 AST_LIST_REMOVE_CURRENT(list); 00877 ast_free(channel); 00878 } 00879 AST_LIST_TRAVERSE_SAFE_END; 00880 AST_LIST_UNLOCK(&dial->channels); 00881 00882 /* Disable any enabled options globally */ 00883 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) { 00884 if (!dial->options[i]) 00885 continue; 00886 if (option_types[i].disable) 00887 option_types[i].disable(dial->options[i]); 00888 dial->options[i] = NULL; 00889 } 00890 00891 /* Lock be gone! */ 00892 ast_mutex_destroy(&dial->lock); 00893 00894 /* Free structure */ 00895 ast_free(dial); 00896 00897 return 0; 00898 }
void ast_dial_hangup | ( | struct ast_dial * | dial | ) |
Hangup channels.
dial | Dialing structure |
Definition at line 825 of file dial.c.
References ast_hangup(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_dial::channels, ast_dial_channel::list, and ast_dial_channel::owner.
Referenced by ast_dial_run(), and page_exec().
00826 { 00827 struct ast_dial_channel *channel = NULL; 00828 00829 if (!dial) 00830 return; 00831 00832 AST_LIST_LOCK(&dial->channels); 00833 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00834 if (channel->owner) { 00835 ast_hangup(channel->owner); 00836 channel->owner = NULL; 00837 } 00838 } 00839 AST_LIST_UNLOCK(&dial->channels); 00840 00841 return; 00842 }
enum ast_dial_result ast_dial_join | ( | struct ast_dial * | dial | ) |
Cancel async thread.
dial | Dialing structure |
Definition at line 777 of file dial.c.
References ast_channel_lock, ast_channel_unlock, AST_DIAL_RESULT_FAILED, AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, chan, ast_dial::channels, ast_dial::lock, ast_dial::state, and ast_dial::thread.
Referenced by dial_trunk(), page_exec(), run_station(), sla_hangup_stations(), sla_ring_station(), and sla_stop_ringing_station().
00778 { 00779 pthread_t thread; 00780 00781 /* If the dial structure is not running in async, return failed */ 00782 if (dial->thread == AST_PTHREADT_NULL) 00783 return AST_DIAL_RESULT_FAILED; 00784 00785 /* Record thread */ 00786 thread = dial->thread; 00787 00788 /* Boom, commence locking */ 00789 ast_mutex_lock(&dial->lock); 00790 00791 /* Stop the thread */ 00792 dial->thread = AST_PTHREADT_STOP; 00793 00794 /* If the answered channel is running an application we have to soft hangup it, can't just poke the thread */ 00795 AST_LIST_LOCK(&dial->channels); 00796 if (AST_LIST_FIRST(&dial->channels)->is_running_app) { 00797 struct ast_channel *chan = AST_LIST_FIRST(&dial->channels)->owner; 00798 if (chan) { 00799 ast_channel_lock(chan); 00800 ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT); 00801 ast_channel_unlock(chan); 00802 } 00803 } else { 00804 /* Now we signal it with SIGURG so it will break out of it's waitfor */ 00805 pthread_kill(thread, SIGURG); 00806 } 00807 AST_LIST_UNLOCK(&dial->channels); 00808 00809 /* Yay done with it */ 00810 ast_mutex_unlock(&dial->lock); 00811 00812 /* Finally wait for the thread to exit */ 00813 pthread_join(thread, NULL); 00814 00815 /* Yay thread is all gone */ 00816 dial->thread = AST_PTHREADT_NULL; 00817 00818 return dial->state; 00819 }
int ast_dial_option_disable | ( | struct ast_dial * | dial, | |
int | num, | |||
enum ast_dial_option | option | |||
) |
Disables an option per channel.
dial | Dial structure | |
num | Channel number to disable option on | |
option | Option to disable |
Definition at line 1001 of file dial.c.
References AST_LIST_EMPTY, ast_dial::channels, ast_option_types::disable, find_dial_channel(), option_types, and ast_dial_channel::options.
01002 { 01003 struct ast_dial_channel *channel = NULL; 01004 01005 /* Ensure we have required arguments */ 01006 if (!dial || AST_LIST_EMPTY(&dial->channels)) 01007 return -1; 01008 01009 if (!(channel = find_dial_channel(dial, num))) 01010 return -1; 01011 01012 /* If the option is not enabled, return failure */ 01013 if (!channel->options[option]) 01014 return -1; 01015 01016 /* Execute callback of option to disable it if it exists */ 01017 if (option_types[option].disable) 01018 option_types[option].disable(channel->options[option]); 01019 01020 /* Finally disable the option on the structure */ 01021 channel->options[option] = NULL; 01022 01023 return 0; 01024 }
int ast_dial_option_enable | ( | struct ast_dial * | dial, | |
int | num, | |||
enum ast_dial_option | option, | |||
void * | data | |||
) |
Enables an option per channel.
dial | Dial structure | |
num | Channel number to enable option on | |
option | Option to enable | |
data | Data to pass to this option (not always needed) |
Definition at line 949 of file dial.c.
References AST_LIST_EMPTY, ast_dial::channels, ast_option_types::enable, find_dial_channel(), option_types, and ast_dial_channel::options.
00950 { 00951 struct ast_dial_channel *channel = NULL; 00952 00953 /* Ensure we have required arguments */ 00954 if (!dial || AST_LIST_EMPTY(&dial->channels)) 00955 return -1; 00956 00957 if (!(channel = find_dial_channel(dial, num))) 00958 return -1; 00959 00960 /* If the option is already enabled, return failure */ 00961 if (channel->options[option]) 00962 return -1; 00963 00964 /* Execute enable callback if it exists, if not simply make sure the value is set */ 00965 if (option_types[option].enable) 00966 channel->options[option] = option_types[option].enable(data); 00967 else 00968 channel->options[option] = (void*)1; 00969 00970 return 0; 00971 }
int ast_dial_option_global_disable | ( | struct ast_dial * | dial, | |
enum ast_dial_option | option | |||
) |
Disables an option globally.
dial | Dial structure to disable option on | |
option | Option to disable |
Definition at line 978 of file dial.c.
References ast_option_types::disable, option_types, and ast_dial::options.
00979 { 00980 /* If the option is not enabled, return failure */ 00981 if (!dial->options[option]) { 00982 return -1; 00983 } 00984 00985 /* Execute callback of option to disable if it exists */ 00986 if (option_types[option].disable) 00987 option_types[option].disable(dial->options[option]); 00988 00989 /* Finally disable option on the structure */ 00990 dial->options[option] = NULL; 00991 00992 return 0; 00993 }
int ast_dial_option_global_enable | ( | struct ast_dial * | dial, | |
enum ast_dial_option | option, | |||
void * | data | |||
) |
Enables an option globally.
dial | Dial structure to enable option on | |
option | Option to enable | |
data | Data to pass to this option (not always needed) |
Definition at line 906 of file dial.c.
References ast_option_types::enable, option_types, and ast_dial::options.
Referenced by page_exec().
00907 { 00908 /* If the option is already enabled, return failure */ 00909 if (dial->options[option]) 00910 return -1; 00911 00912 /* Execute enable callback if it exists, if not simply make sure the value is set */ 00913 if (option_types[option].enable) 00914 dial->options[option] = option_types[option].enable(data); 00915 else 00916 dial->options[option] = (void*)1; 00917 00918 return 0; 00919 }
enum ast_dial_result ast_dial_run | ( | struct ast_dial * | dial, | |
struct ast_channel * | chan, | |||
int | async | |||
) |
Execute dialing synchronously or asynchronously.
Definition at line 697 of file dial.c.
References ast_debug, ast_dial_hangup(), AST_DIAL_RESULT_FAILED, AST_DIAL_RESULT_INVALID, AST_DIAL_RESULT_TRYING, AST_LIST_EMPTY, ast_pthread_create, async_dial(), begin_dial(), chan, ast_dial::channels, monitor_dial(), ast_dial::state, and ast_dial::thread.
Referenced by dial_trunk(), page_exec(), and sla_ring_station().
00698 { 00699 enum ast_dial_result res = AST_DIAL_RESULT_TRYING; 00700 00701 /* Ensure required arguments are passed */ 00702 if (!dial || (!chan && !async)) { 00703 ast_debug(1, "invalid #1\n"); 00704 return AST_DIAL_RESULT_INVALID; 00705 } 00706 00707 /* If there are no channels to dial we can't very well try to dial them */ 00708 if (AST_LIST_EMPTY(&dial->channels)) { 00709 ast_debug(1, "invalid #2\n"); 00710 return AST_DIAL_RESULT_INVALID; 00711 } 00712 00713 /* Dial each requested channel */ 00714 if (!begin_dial(dial, chan)) 00715 return AST_DIAL_RESULT_FAILED; 00716 00717 /* If we are running async spawn a thread and send it away... otherwise block here */ 00718 if (async) { 00719 dial->state = AST_DIAL_RESULT_TRYING; 00720 /* Try to create a thread */ 00721 if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) { 00722 /* Failed to create the thread - hangup all dialed channels and return failed */ 00723 ast_dial_hangup(dial); 00724 res = AST_DIAL_RESULT_FAILED; 00725 } 00726 } else { 00727 res = monitor_dial(dial, chan); 00728 } 00729 00730 return res; 00731 }
void ast_dial_set_global_timeout | ( | struct ast_dial * | dial, | |
int | timeout | |||
) |
Set the maximum time (globally) allowed for trying to ring phones.
dial | The dial structure to apply the time limit to | |
timeout | Maximum time allowed |
Definition at line 1036 of file dial.c.
References ast_dial::actual_timeout, and ast_dial::timeout.
01037 { 01038 dial->timeout = timeout; 01039 01040 if (dial->timeout > 0 && dial->actual_timeout > dial->timeout) 01041 dial->actual_timeout = dial->timeout; 01042 01043 return; 01044 }
void ast_dial_set_state_callback | ( | struct ast_dial * | dial, | |
ast_dial_state_callback | callback | |||
) |
Set a callback for state changes.
dial | The dial structure to watch for state changes | |
callback | the callback |
Definition at line 1026 of file dial.c.
References ast_dial::state_callback.
Referenced by sla_ring_station().
01027 { 01028 dial->state_callback = callback; 01029 }
void ast_dial_set_timeout | ( | struct ast_dial * | dial, | |
int | num, | |||
int | timeout | |||
) |
Set the maximum time (per channel) allowed for trying to ring the phone.
dial | The dial structure the channel belongs to | |
num | Channel number to set timeout on | |
timeout | Maximum time allowed |
Definition at line 1052 of file dial.c.
References ast_dial::actual_timeout, find_dial_channel(), and ast_dial_channel::timeout.
01053 { 01054 struct ast_dial_channel *channel = NULL; 01055 01056 if (!(channel = find_dial_channel(dial, num))) 01057 return; 01058 01059 channel->timeout = timeout; 01060 01061 if (channel->timeout > 0 && dial->actual_timeout > channel->timeout) 01062 dial->actual_timeout = channel->timeout; 01063 01064 return; 01065 }
enum ast_dial_result ast_dial_state | ( | struct ast_dial * | dial | ) |
Return state of dial.
dial | Dialing structure |
Definition at line 768 of file dial.c.
References ast_dial::state.
Referenced by dial_trunk(), and sla_handle_dial_state_event().
00769 { 00770 return dial->state; 00771 }
static void* async_dial | ( | void * | data | ) | [static] |
Dial async thread function.
Definition at line 683 of file dial.c.
References monitor_dial().
Referenced by ast_dial_run().
00684 { 00685 struct ast_dial *dial = data; 00686 00687 /* This is really really simple... we basically pass monitor_dial a NULL owner and it changes it's behavior */ 00688 monitor_dial(dial, NULL); 00689 00690 return NULL; 00691 }
static int begin_dial | ( | struct ast_dial * | dial, | |
struct ast_channel * | chan | |||
) | [static] |
Helper function that does the beginning dialing per dial structure.
Definition at line 310 of file dial.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, begin_dial_channel(), chan, ast_dial::channels, and ast_dial_channel::list.
Referenced by ast_dial_run().
00311 { 00312 struct ast_dial_channel *channel = NULL; 00313 int success = 0; 00314 00315 /* Iterate through channel list, requesting and calling each one */ 00316 AST_LIST_LOCK(&dial->channels); 00317 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00318 success += begin_dial_channel(channel, chan); 00319 } 00320 AST_LIST_UNLOCK(&dial->channels); 00321 00322 /* If number of failures matches the number of channels, then this truly failed */ 00323 return success; 00324 }
static int begin_dial_channel | ( | struct ast_dial_channel * | channel, | |
struct ast_channel * | chan | |||
) | [static] |
Helper function that does the beginning dialing per-appended channel.
Definition at line 255 of file dial.c.
References accountcode, ast_channel::adsicpe, ast_channel::appl, ast_call(), ast_channel_inherit_variables(), ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_hangup(), AST_MAX_EXTENSION, ast_poll_channel_add(), ast_request(), ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_verb, ast_dial_channel::cause, ast_channel::cdrflags, chan, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::data, ast_dial_channel::device, language, musicclass, ast_channel::musicclass, ast_channel::nativeformats, ast_dial_channel::owner, S_REPLACE, ast_dial_channel::tech, ast_channel::transfercapability, and ast_channel::whentohangup.
Referenced by begin_dial(), and handle_call_forward().
00256 { 00257 char numsubst[AST_MAX_EXTENSION]; 00258 int res = 1; 00259 00260 /* Copy device string over */ 00261 ast_copy_string(numsubst, channel->device, sizeof(numsubst)); 00262 00263 /* If we fail to create our owner channel bail out */ 00264 if (!(channel->owner = ast_request(channel->tech, chan ? chan->nativeformats : AST_FORMAT_AUDIO_MASK, numsubst, &channel->cause))) 00265 return -1; 00266 00267 channel->owner->appl = "AppDial2"; 00268 channel->owner->data = "(Outgoing Line)"; 00269 channel->owner->whentohangup = 0; 00270 00271 /* Inherit everything from he who spawned this dial */ 00272 if (chan) { 00273 ast_channel_inherit_variables(chan, channel->owner); 00274 00275 /* Copy over callerid information */ 00276 S_REPLACE(channel->owner->cid.cid_num, ast_strdup(chan->cid.cid_num)); 00277 S_REPLACE(channel->owner->cid.cid_name, ast_strdup(chan->cid.cid_name)); 00278 S_REPLACE(channel->owner->cid.cid_ani, ast_strdup(chan->cid.cid_ani)); 00279 S_REPLACE(channel->owner->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis)); 00280 00281 ast_string_field_set(channel->owner, language, chan->language); 00282 ast_string_field_set(channel->owner, accountcode, chan->accountcode); 00283 channel->owner->cdrflags = chan->cdrflags; 00284 if (ast_strlen_zero(channel->owner->musicclass)) 00285 ast_string_field_set(channel->owner, musicclass, chan->musicclass); 00286 00287 channel->owner->cid.cid_pres = chan->cid.cid_pres; 00288 channel->owner->cid.cid_ton = chan->cid.cid_ton; 00289 channel->owner->cid.cid_tns = chan->cid.cid_tns; 00290 channel->owner->adsicpe = chan->adsicpe; 00291 channel->owner->transfercapability = chan->transfercapability; 00292 } 00293 00294 /* Attempt to actually call this device */ 00295 if ((res = ast_call(channel->owner, numsubst, 0))) { 00296 res = 0; 00297 ast_hangup(channel->owner); 00298 channel->owner = NULL; 00299 } else { 00300 if (chan) 00301 ast_poll_channel_add(chan, channel->owner); 00302 res = 1; 00303 ast_verb(3, "Called %s\n", numsubst); 00304 } 00305 00306 return res; 00307 }
static struct ast_dial_channel* find_dial_channel | ( | struct ast_dial * | dial, | |
int | num | |||
) | [static] |
Helper function for finding a channel in a dial structure based on number.
Definition at line 923 of file dial.c.
References AST_LIST_LAST, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_dial::channels, ast_dial_channel::list, and ast_dial_channel::num.
Referenced by ast_dial_option_disable(), ast_dial_option_enable(), and ast_dial_set_timeout().
00924 { 00925 struct ast_dial_channel *channel = AST_LIST_LAST(&dial->channels); 00926 00927 /* We can try to predict programmer behavior, the last channel they added is probably the one they wanted to modify */ 00928 if (channel->num == num) 00929 return channel; 00930 00931 /* Hrm not at the end... looking through the list it is! */ 00932 AST_LIST_LOCK(&dial->channels); 00933 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00934 if (channel->num == num) 00935 break; 00936 } 00937 AST_LIST_UNLOCK(&dial->channels); 00938 00939 return channel; 00940 }
static struct ast_dial_channel* find_relative_dial_channel | ( | struct ast_dial * | dial, | |
struct ast_channel * | owner | |||
) | [static] |
Helper function that finds the dialed channel based on owner.
Definition at line 366 of file dial.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_dial::channels, ast_dial_channel::list, and ast_dial_channel::owner.
Referenced by monitor_dial().
00367 { 00368 struct ast_dial_channel *channel = NULL; 00369 00370 AST_LIST_LOCK(&dial->channels); 00371 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00372 if (channel->owner == owner) 00373 break; 00374 } 00375 AST_LIST_UNLOCK(&dial->channels); 00376 00377 return channel; 00378 }
static int handle_call_forward | ( | struct ast_dial * | dial, | |
struct ast_dial_channel * | channel, | |||
struct ast_channel * | chan | |||
) | [static] |
Helper function to handle channels that have been call forwarded.
Definition at line 327 of file dial.c.
References AST_DIAL_OPTION_DISABLE_CALL_FORWARDING, ast_free, ast_hangup(), AST_LIST_UNLOCK, ast_strdup, ast_strdupa, begin_dial_channel(), ast_channel::call_forward, chan, ast_dial::channels, ast_dial_channel::device, FIND_RELATIVE_OPTION, ast_dial_channel::owner, and ast_dial_channel::tech.
Referenced by monitor_dial().
00328 { 00329 struct ast_channel *original = channel->owner; 00330 char *tmp = ast_strdupa(channel->owner->call_forward); 00331 char *tech = "Local", *device = tmp, *stuff; 00332 00333 /* If call forwarding is disabled just drop the original channel and don't attempt to dial the new one */ 00334 if (FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_DISABLE_CALL_FORWARDING)) { 00335 ast_hangup(original); 00336 channel->owner = NULL; 00337 return 0; 00338 } 00339 00340 /* Figure out the new destination */ 00341 if ((stuff = strchr(tmp, '/'))) { 00342 *stuff++ = '\0'; 00343 tech = tmp; 00344 device = stuff; 00345 } 00346 00347 /* Drop old destination information */ 00348 ast_free(channel->tech); 00349 ast_free(channel->device); 00350 00351 /* Update the dial channel with the new destination information */ 00352 channel->tech = ast_strdup(tech); 00353 channel->device = ast_strdup(device); 00354 AST_LIST_UNLOCK(&dial->channels); 00355 00356 /* Finally give it a go... send it out into the world */ 00357 begin_dial_channel(channel, chan); 00358 00359 /* Drop the original channel */ 00360 ast_hangup(original); 00361 00362 return 0; 00363 }
static void handle_frame | ( | struct ast_dial * | dial, | |
struct ast_dial_channel * | channel, | |||
struct ast_frame * | fr, | |||
struct ast_channel * | chan | |||
) | [static] |
Helper function that handles control frames WITH owner.
Definition at line 389 of file dial.c.
References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, 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_DIAL_OPTION_MUSIC, AST_DIAL_RESULT_ANSWERED, AST_DIAL_RESULT_PROCEEDING, AST_DIAL_RESULT_PROGRESS, AST_DIAL_RESULT_RINGING, AST_FRAME_CONTROL, ast_hangup(), ast_indicate(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_verb, ast_verbose(), chan, ast_dial::channels, ast_frame::frametype, ast_dial_channel::list, ast_channel::name, option_verbose, ast_dial::options, ast_dial_channel::owner, set_state(), ast_frame::subclass, and VERBOSE_PREFIX_3.
Referenced by monitor_dial(), and socket_read().
00390 { 00391 if (fr->frametype == AST_FRAME_CONTROL) { 00392 switch (fr->subclass) { 00393 case AST_CONTROL_ANSWER: 00394 ast_verb(3, "%s answered %s\n", channel->owner->name, chan->name); 00395 AST_LIST_LOCK(&dial->channels); 00396 AST_LIST_REMOVE(&dial->channels, channel, list); 00397 AST_LIST_INSERT_HEAD(&dial->channels, channel, list); 00398 AST_LIST_UNLOCK(&dial->channels); 00399 set_state(dial, AST_DIAL_RESULT_ANSWERED); 00400 break; 00401 case AST_CONTROL_BUSY: 00402 ast_verb(3, "%s is busy\n", channel->owner->name); 00403 ast_hangup(channel->owner); 00404 channel->owner = NULL; 00405 break; 00406 case AST_CONTROL_CONGESTION: 00407 ast_verb(3, "%s is circuit-busy\n", channel->owner->name); 00408 ast_hangup(channel->owner); 00409 channel->owner = NULL; 00410 break; 00411 case AST_CONTROL_RINGING: 00412 ast_verb(3, "%s is ringing\n", channel->owner->name); 00413 if (!dial->options[AST_DIAL_OPTION_MUSIC]) 00414 ast_indicate(chan, AST_CONTROL_RINGING); 00415 set_state(dial, AST_DIAL_RESULT_RINGING); 00416 break; 00417 case AST_CONTROL_PROGRESS: 00418 ast_verb(3, "%s is making progress, passing it to %s\n", channel->owner->name, chan->name); 00419 ast_indicate(chan, AST_CONTROL_PROGRESS); 00420 set_state(dial, AST_DIAL_RESULT_PROGRESS); 00421 break; 00422 case AST_CONTROL_VIDUPDATE: 00423 ast_verb(3, "%s requested a video update, passing it to %s\n", channel->owner->name, chan->name); 00424 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 00425 break; 00426 case AST_CONTROL_SRCUPDATE: 00427 if (option_verbose > 2) 00428 ast_verbose (VERBOSE_PREFIX_3 "%s requested a source update, passing it to %s\n", channel->owner->name, chan->name); 00429 ast_indicate(chan, AST_CONTROL_SRCUPDATE); 00430 break; 00431 case AST_CONTROL_PROCEEDING: 00432 ast_verb(3, "%s is proceeding, passing it to %s\n", channel->owner->name, chan->name); 00433 ast_indicate(chan, AST_CONTROL_PROCEEDING); 00434 set_state(dial, AST_DIAL_RESULT_PROCEEDING); 00435 break; 00436 case AST_CONTROL_HOLD: 00437 ast_verb(3, "Call on %s placed on hold\n", chan->name); 00438 ast_indicate(chan, AST_CONTROL_HOLD); 00439 break; 00440 case AST_CONTROL_UNHOLD: 00441 ast_verb(3, "Call on %s left from hold\n", chan->name); 00442 ast_indicate(chan, AST_CONTROL_UNHOLD); 00443 break; 00444 case AST_CONTROL_OFFHOOK: 00445 case AST_CONTROL_FLASH: 00446 break; 00447 case -1: 00448 /* Prod the channel */ 00449 ast_indicate(chan, -1); 00450 break; 00451 default: 00452 break; 00453 } 00454 } 00455 00456 return; 00457 }
static void handle_frame_ownerless | ( | struct ast_dial * | dial, | |
struct ast_dial_channel * | channel, | |||
struct ast_frame * | fr | |||
) | [static] |
Helper function that handles control frames WITHOUT owner.
Definition at line 460 of file dial.c.
References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_DIAL_RESULT_ANSWERED, AST_DIAL_RESULT_PROCEEDING, AST_DIAL_RESULT_PROGRESS, AST_DIAL_RESULT_RINGING, AST_FRAME_CONTROL, ast_hangup(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_verb, ast_dial::channels, ast_frame::frametype, ast_dial_channel::list, ast_channel::name, ast_dial_channel::owner, set_state(), and ast_frame::subclass.
Referenced by monitor_dial().
00461 { 00462 /* If we have no owner we can only update the state of the dial structure, so only look at control frames */ 00463 if (fr->frametype != AST_FRAME_CONTROL) 00464 return; 00465 00466 switch (fr->subclass) { 00467 case AST_CONTROL_ANSWER: 00468 ast_verb(3, "%s answered\n", channel->owner->name); 00469 AST_LIST_LOCK(&dial->channels); 00470 AST_LIST_REMOVE(&dial->channels, channel, list); 00471 AST_LIST_INSERT_HEAD(&dial->channels, channel, list); 00472 AST_LIST_UNLOCK(&dial->channels); 00473 set_state(dial, AST_DIAL_RESULT_ANSWERED); 00474 break; 00475 case AST_CONTROL_BUSY: 00476 ast_verb(3, "%s is busy\n", channel->owner->name); 00477 ast_hangup(channel->owner); 00478 channel->owner = NULL; 00479 break; 00480 case AST_CONTROL_CONGESTION: 00481 ast_verb(3, "%s is circuit-busy\n", channel->owner->name); 00482 ast_hangup(channel->owner); 00483 channel->owner = NULL; 00484 break; 00485 case AST_CONTROL_RINGING: 00486 ast_verb(3, "%s is ringing\n", channel->owner->name); 00487 set_state(dial, AST_DIAL_RESULT_RINGING); 00488 break; 00489 case AST_CONTROL_PROGRESS: 00490 ast_verb(3, "%s is making progress\n", channel->owner->name); 00491 set_state(dial, AST_DIAL_RESULT_PROGRESS); 00492 break; 00493 case AST_CONTROL_PROCEEDING: 00494 ast_verb(3, "%s is proceeding\n", channel->owner->name); 00495 set_state(dial, AST_DIAL_RESULT_PROCEEDING); 00496 break; 00497 default: 00498 break; 00499 } 00500 00501 return; 00502 }
static int handle_timeout_trip | ( | struct ast_dial * | dial, | |
struct timeval | start | |||
) | [static] |
Helper function to handle when a timeout occurs on dialing attempt.
Definition at line 505 of file dial.c.
References AST_DIAL_RESULT_TIMEOUT, ast_hangup(), AST_LIST_TRAVERSE, ast_tvdiff_ms(), ast_tvnow(), ast_dial::channels, ast_dial_channel::list, ast_dial_channel::owner, set_state(), ast_dial::state, ast_dial_channel::timeout, and ast_dial::timeout.
Referenced by monitor_dial().
00506 { 00507 struct ast_dial_channel *channel = NULL; 00508 int diff = ast_tvdiff_ms(ast_tvnow(), start), lowest_timeout = -1, new_timeout = -1; 00509 00510 /* If the global dial timeout tripped switch the state to timeout so our channel loop will drop every channel */ 00511 if (diff >= dial->timeout) { 00512 set_state(dial, AST_DIAL_RESULT_TIMEOUT); 00513 new_timeout = 0; 00514 } 00515 00516 /* Go through dropping out channels that have met their timeout */ 00517 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00518 if (dial->state == AST_DIAL_RESULT_TIMEOUT || diff >= channel->timeout) { 00519 ast_hangup(channel->owner); 00520 channel->owner = NULL; 00521 } else if ((lowest_timeout == -1) || (lowest_timeout > channel->timeout)) { 00522 lowest_timeout = channel->timeout; 00523 } 00524 } 00525 00526 /* Calculate the new timeout using the lowest timeout found */ 00527 if (lowest_timeout >= 0) 00528 new_timeout = lowest_timeout - diff; 00529 00530 return new_timeout; 00531 }
static enum ast_dial_result monitor_dial | ( | struct ast_dial * | dial, | |
struct ast_channel * | chan | |||
) | [static] |
Helper function that basically keeps tabs on dialing attempts.
Definition at line 534 of file dial.c.
References ast_dial::actual_timeout, answer_exec_run(), answer_exec_struct::app, answer_exec_struct::args, AST_CONTROL_RINGING, AST_DIAL_OPTION_ANSWER_EXEC, AST_DIAL_OPTION_MUSIC, AST_DIAL_OPTION_RINGING, AST_DIAL_RESULT_ANSWERED, AST_DIAL_RESULT_HANGUP, AST_DIAL_RESULT_RINGING, AST_DIAL_RESULT_TIMEOUT, AST_DIAL_RESULT_TRYING, AST_DIAL_RESULT_UNANSWERED, ast_frfree, ast_hangup(), ast_indicate(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MAX_WATCHERS, ast_moh_start(), ast_moh_stop(), ast_poll_channel_del(), AST_PTHREADT_STOP, ast_read(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_tvnow(), ast_waitfor_n(), ast_channel::call_forward, chan, ast_dial::channels, find_relative_dial_channel(), FIND_RELATIVE_OPTION, handle_call_forward(), handle_frame(), handle_frame_ownerless(), handle_timeout_trip(), IS_CALLER, ast_dial_channel::is_running_app, musicclass, ast_channel::musicclass, ast_dial::options, ast_dial_channel::owner, set_state(), ast_dial::state, and ast_dial::thread.
Referenced by ast_dial_run(), and async_dial().
00535 { 00536 int timeout = -1; 00537 struct ast_channel *cs[AST_MAX_WATCHERS], *who = NULL; 00538 struct ast_dial_channel *channel = NULL; 00539 struct answer_exec_struct *answer_exec = NULL; 00540 struct timeval start; 00541 00542 set_state(dial, AST_DIAL_RESULT_TRYING); 00543 00544 /* If the "always indicate ringing" option is set, change state to ringing and indicate to the owner if present */ 00545 if (dial->options[AST_DIAL_OPTION_RINGING]) { 00546 set_state(dial, AST_DIAL_RESULT_RINGING); 00547 if (chan) 00548 ast_indicate(chan, AST_CONTROL_RINGING); 00549 } else if (chan && dial->options[AST_DIAL_OPTION_MUSIC] && 00550 !ast_strlen_zero(dial->options[AST_DIAL_OPTION_MUSIC])) { 00551 char *original_moh = ast_strdupa(chan->musicclass); 00552 ast_indicate(chan, -1); 00553 ast_string_field_set(chan, musicclass, dial->options[AST_DIAL_OPTION_MUSIC]); 00554 ast_moh_start(chan, dial->options[AST_DIAL_OPTION_MUSIC], NULL); 00555 ast_string_field_set(chan, musicclass, original_moh); 00556 } 00557 00558 /* Record start time for timeout purposes */ 00559 start = ast_tvnow(); 00560 00561 /* We actually figured out the maximum timeout we can do as they were added, so we can directly access the info */ 00562 timeout = dial->actual_timeout; 00563 00564 /* Go into an infinite loop while we are trying */ 00565 while ((dial->state != AST_DIAL_RESULT_UNANSWERED) && (dial->state != AST_DIAL_RESULT_ANSWERED) && (dial->state != AST_DIAL_RESULT_HANGUP) && (dial->state != AST_DIAL_RESULT_TIMEOUT)) { 00566 int pos = 0, count = 0; 00567 struct ast_frame *fr = NULL; 00568 00569 /* Set up channel structure array */ 00570 pos = count = 0; 00571 if (chan) 00572 cs[pos++] = chan; 00573 00574 /* Add channels we are attempting to dial */ 00575 AST_LIST_LOCK(&dial->channels); 00576 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00577 if (channel->owner) { 00578 cs[pos++] = channel->owner; 00579 count++; 00580 } 00581 } 00582 AST_LIST_UNLOCK(&dial->channels); 00583 00584 /* If we have no outbound channels in progress, switch state to unanswered and stop */ 00585 if (!count) { 00586 set_state(dial, AST_DIAL_RESULT_UNANSWERED); 00587 break; 00588 } 00589 00590 /* Just to be safe... */ 00591 if (dial->thread == AST_PTHREADT_STOP) 00592 break; 00593 00594 /* Wait for frames from channels */ 00595 who = ast_waitfor_n(cs, pos, &timeout); 00596 00597 /* Check to see if our thread is being cancelled */ 00598 if (dial->thread == AST_PTHREADT_STOP) 00599 break; 00600 00601 /* If the timeout no longer exists OR if we got no channel it basically means the timeout was tripped, so handle it */ 00602 if (!timeout || !who) { 00603 timeout = handle_timeout_trip(dial, start); 00604 continue; 00605 } 00606 00607 /* Find relative dial channel */ 00608 if (!chan || !IS_CALLER(chan, who)) 00609 channel = find_relative_dial_channel(dial, who); 00610 00611 /* See if this channel has been forwarded elsewhere */ 00612 if (!ast_strlen_zero(who->call_forward)) { 00613 handle_call_forward(dial, channel, chan); 00614 continue; 00615 } 00616 00617 /* Attempt to read in a frame */ 00618 if (!(fr = ast_read(who))) { 00619 /* If this is the caller then we switch state to hangup and stop */ 00620 if (chan && IS_CALLER(chan, who)) { 00621 set_state(dial, AST_DIAL_RESULT_HANGUP); 00622 break; 00623 } 00624 if (chan) 00625 ast_poll_channel_del(chan, channel->owner); 00626 ast_hangup(who); 00627 channel->owner = NULL; 00628 continue; 00629 } 00630 00631 /* Process the frame */ 00632 if (chan) 00633 handle_frame(dial, channel, fr, chan); 00634 else 00635 handle_frame_ownerless(dial, channel, fr); 00636 00637 /* Free the received frame and start all over */ 00638 ast_frfree(fr); 00639 } 00640 00641 /* Do post-processing from loop */ 00642 if (dial->state == AST_DIAL_RESULT_ANSWERED) { 00643 /* Hangup everything except that which answered */ 00644 AST_LIST_LOCK(&dial->channels); 00645 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00646 if (!channel->owner || channel->owner == who) 00647 continue; 00648 if (chan) 00649 ast_poll_channel_del(chan, channel->owner); 00650 ast_hangup(channel->owner); 00651 channel->owner = NULL; 00652 } 00653 AST_LIST_UNLOCK(&dial->channels); 00654 /* If ANSWER_EXEC is enabled as an option, execute application on answered channel */ 00655 if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC))) { 00656 channel->is_running_app = 1; 00657 answer_exec_run(dial, channel, answer_exec->app, answer_exec->args); 00658 channel->is_running_app = 0; 00659 } 00660 00661 if (chan && dial->options[AST_DIAL_OPTION_MUSIC] && 00662 !ast_strlen_zero(dial->options[AST_DIAL_OPTION_MUSIC])) { 00663 ast_moh_stop(chan); 00664 } 00665 } else if (dial->state == AST_DIAL_RESULT_HANGUP) { 00666 /* Hangup everything */ 00667 AST_LIST_LOCK(&dial->channels); 00668 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00669 if (!channel->owner) 00670 continue; 00671 if (chan) 00672 ast_poll_channel_del(chan, channel->owner); 00673 ast_hangup(channel->owner); 00674 channel->owner = NULL; 00675 } 00676 AST_LIST_UNLOCK(&dial->channels); 00677 } 00678 00679 return dial->state; 00680 }
static int music_disable | ( | void * | data | ) | [static] |
static void* music_enable | ( | void * | data | ) | [static] |
Definition at line 124 of file dial.c.
References ast_strdup.
00125 { 00126 return ast_strdup(data); 00127 }
static void set_state | ( | struct ast_dial * | dial, | |
enum ast_dial_result | state | |||
) | [static] |
Definition at line 380 of file dial.c.
References ast_dial::state, and ast_dial::state_callback.
Referenced by handle_frame(), handle_frame_ownerless(), handle_timeout_trip(), and monitor_dial().
00381 { 00382 dial->state = state; 00383 00384 if (dial->state_callback) 00385 dial->state_callback(dial); 00386 }
struct ast_option_types option_types[] [static] |
Options structure - maps options to respective handlers (enable/disable). This list MUST be perfectly kept in order, or else madness will happen.
Referenced by ast_dial_destroy(), ast_dial_option_disable(), ast_dial_option_enable(), ast_dial_option_global_disable(), and ast_dial_option_global_enable().