Dialing API. More...
#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. | |
| struct ast_channel * | ast_dial_answered (struct ast_dial *dial) |
| Return channel that answered. | |
| struct 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. | |
| struct 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. | |
Dialing API.
Definition in file dial.c.
| #define AST_MAX_WATCHERS 256 |
| #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 | ) |
| 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 answer_exec_struct::app, app, answer_exec_struct::args, ast_calloc, ast_copy_string(), ast_strdup, 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 | ) | [read] |
Return channel that answered.
| dial | Dialing structure |
Definition at line 738 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().
00739 { 00740 if (!dial) 00741 return NULL; 00742 00743 return ((dial->state == AST_DIAL_RESULT_ANSWERED) ? AST_LIST_FIRST(&dial->channels)->owner : NULL); 00744 }
| struct ast_channel* ast_dial_answered_steal | ( | struct ast_dial * | dial | ) | [read] |
Steal the channel that answered.
| dial | Dialing structure |
Definition at line 750 of file dial.c.
References AST_DIAL_RESULT_ANSWERED, AST_LIST_FIRST, chan, ast_dial::channels, and ast_dial::state.
00751 { 00752 struct ast_channel *chan = NULL; 00753 00754 if (!dial) 00755 return NULL; 00756 00757 if (dial->state == AST_DIAL_RESULT_ANSWERED) { 00758 chan = AST_LIST_FIRST(&dial->channels)->owner; 00759 AST_LIST_FIRST(&dial->channels)->owner = NULL; 00760 } 00761 00762 return chan; 00763 }
| 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::device, ast_dial_channel::list, ast_dial::num, ast_dial_channel::num, ast_dial_channel::tech, and ast_dial_channel::timeout.
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 | ) | [read] |
New dialing structure.
Definition at line 198 of file dial.c.
References ast_dial::actual_timeout, ast_calloc, AST_LIST_HEAD_INIT, ast_mutex_init(), AST_PTHREADT_NULL, ast_dial::channels, ast_dial::lock, ast_dial::thread, and ast_dial::timeout.
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 850 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_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_mutex_destroy(), ast_dial::channels, ast_dial_channel::device, ast_option_types::disable, ast_dial_channel::list, ast_dial::lock, option_types, ast_dial::options, 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().
00851 { 00852 int i = 0; 00853 struct ast_dial_channel *channel = NULL; 00854 00855 if (!dial) 00856 return -1; 00857 00858 /* Hangup and deallocate all the dialed channels */ 00859 AST_LIST_LOCK(&dial->channels); 00860 AST_LIST_TRAVERSE_SAFE_BEGIN(&dial->channels, channel, list) { 00861 /* Disable any enabled options */ 00862 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) { 00863 if (!channel->options[i]) 00864 continue; 00865 if (option_types[i].disable) 00866 option_types[i].disable(channel->options[i]); 00867 channel->options[i] = NULL; 00868 } 00869 /* Hang up channel if need be */ 00870 if (channel->owner) { 00871 ast_hangup(channel->owner); 00872 channel->owner = NULL; 00873 } 00874 /* Free structure */ 00875 ast_free(channel->tech); 00876 ast_free(channel->device); 00877 AST_LIST_REMOVE_CURRENT(list); 00878 ast_free(channel); 00879 } 00880 AST_LIST_TRAVERSE_SAFE_END; 00881 AST_LIST_UNLOCK(&dial->channels); 00882 00883 /* Disable any enabled options globally */ 00884 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) { 00885 if (!dial->options[i]) 00886 continue; 00887 if (option_types[i].disable) 00888 option_types[i].disable(dial->options[i]); 00889 dial->options[i] = NULL; 00890 } 00891 00892 /* Lock be gone! */ 00893 ast_mutex_destroy(&dial->lock); 00894 00895 /* Free structure */ 00896 ast_free(dial); 00897 00898 return 0; 00899 }
| void ast_dial_hangup | ( | struct ast_dial * | dial | ) |
Hangup channels.
| dial | Dialing structure |
Definition at line 826 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().
00827 { 00828 struct ast_dial_channel *channel = NULL; 00829 00830 if (!dial) 00831 return; 00832 00833 AST_LIST_LOCK(&dial->channels); 00834 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00835 if (channel->owner) { 00836 ast_hangup(channel->owner); 00837 channel->owner = NULL; 00838 } 00839 } 00840 AST_LIST_UNLOCK(&dial->channels); 00841 00842 return; 00843 }
| enum ast_dial_result ast_dial_join | ( | struct ast_dial * | dial | ) |
Cancel async thread.
| dial | Dialing structure |
Definition at line 778 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().
00779 { 00780 pthread_t thread; 00781 00782 /* If the dial structure is not running in async, return failed */ 00783 if (dial->thread == AST_PTHREADT_NULL) 00784 return AST_DIAL_RESULT_FAILED; 00785 00786 /* Record thread */ 00787 thread = dial->thread; 00788 00789 /* Boom, commence locking */ 00790 ast_mutex_lock(&dial->lock); 00791 00792 /* Stop the thread */ 00793 dial->thread = AST_PTHREADT_STOP; 00794 00795 /* If the answered channel is running an application we have to soft hangup it, can't just poke the thread */ 00796 AST_LIST_LOCK(&dial->channels); 00797 if (AST_LIST_FIRST(&dial->channels)->is_running_app) { 00798 struct ast_channel *chan = AST_LIST_FIRST(&dial->channels)->owner; 00799 if (chan) { 00800 ast_channel_lock(chan); 00801 ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT); 00802 ast_channel_unlock(chan); 00803 } 00804 } else { 00805 /* Now we signal it with SIGURG so it will break out of it's waitfor */ 00806 pthread_kill(thread, SIGURG); 00807 } 00808 AST_LIST_UNLOCK(&dial->channels); 00809 00810 /* Yay done with it */ 00811 ast_mutex_unlock(&dial->lock); 00812 00813 /* Finally wait for the thread to exit */ 00814 pthread_join(thread, NULL); 00815 00816 /* Yay thread is all gone */ 00817 dial->thread = AST_PTHREADT_NULL; 00818 00819 return dial->state; 00820 }
| 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 1002 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.
01003 { 01004 struct ast_dial_channel *channel = NULL; 01005 01006 /* Ensure we have required arguments */ 01007 if (!dial || AST_LIST_EMPTY(&dial->channels)) 01008 return -1; 01009 01010 if (!(channel = find_dial_channel(dial, num))) 01011 return -1; 01012 01013 /* If the option is not enabled, return failure */ 01014 if (!channel->options[option]) 01015 return -1; 01016 01017 /* Execute callback of option to disable it if it exists */ 01018 if (option_types[option].disable) 01019 option_types[option].disable(channel->options[option]); 01020 01021 /* Finally disable the option on the structure */ 01022 channel->options[option] = NULL; 01023 01024 return 0; 01025 }
| 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 950 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.
00951 { 00952 struct ast_dial_channel *channel = NULL; 00953 00954 /* Ensure we have required arguments */ 00955 if (!dial || AST_LIST_EMPTY(&dial->channels)) 00956 return -1; 00957 00958 if (!(channel = find_dial_channel(dial, num))) 00959 return -1; 00960 00961 /* If the option is already enabled, return failure */ 00962 if (channel->options[option]) 00963 return -1; 00964 00965 /* Execute enable callback if it exists, if not simply make sure the value is set */ 00966 if (option_types[option].enable) 00967 channel->options[option] = option_types[option].enable(data); 00968 else 00969 channel->options[option] = (void*)1; 00970 00971 return 0; 00972 }
| 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 979 of file dial.c.
References ast_option_types::disable, option_types, and ast_dial::options.
00980 { 00981 /* If the option is not enabled, return failure */ 00982 if (!dial->options[option]) { 00983 return -1; 00984 } 00985 00986 /* Execute callback of option to disable if it exists */ 00987 if (option_types[option].disable) 00988 option_types[option].disable(dial->options[option]); 00989 00990 /* Finally disable option on the structure */ 00991 dial->options[option] = NULL; 00992 00993 return 0; 00994 }
| 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 907 of file dial.c.
References ast_option_types::enable, option_types, and ast_dial::options.
Referenced by page_exec().
00908 { 00909 /* If the option is already enabled, return failure */ 00910 if (dial->options[option]) 00911 return -1; 00912 00913 /* Execute enable callback if it exists, if not simply make sure the value is set */ 00914 if (option_types[option].enable) 00915 dial->options[option] = option_types[option].enable(data); 00916 else 00917 dial->options[option] = (void*)1; 00918 00919 return 0; 00920 }
| 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 698 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(), ast_dial::channels, monitor_dial(), ast_dial::state, and ast_dial::thread.
Referenced by dial_trunk(), page_exec(), and sla_ring_station().
00699 { 00700 enum ast_dial_result res = AST_DIAL_RESULT_TRYING; 00701 00702 /* Ensure required arguments are passed */ 00703 if (!dial || (!chan && !async)) { 00704 ast_debug(1, "invalid #1\n"); 00705 return AST_DIAL_RESULT_INVALID; 00706 } 00707 00708 /* If there are no channels to dial we can't very well try to dial them */ 00709 if (AST_LIST_EMPTY(&dial->channels)) { 00710 ast_debug(1, "invalid #2\n"); 00711 return AST_DIAL_RESULT_INVALID; 00712 } 00713 00714 /* Dial each requested channel */ 00715 if (!begin_dial(dial, chan)) 00716 return AST_DIAL_RESULT_FAILED; 00717 00718 /* If we are running async spawn a thread and send it away... otherwise block here */ 00719 if (async) { 00720 dial->state = AST_DIAL_RESULT_TRYING; 00721 /* Try to create a thread */ 00722 if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) { 00723 /* Failed to create the thread - hangup all dialed channels and return failed */ 00724 ast_dial_hangup(dial); 00725 res = AST_DIAL_RESULT_FAILED; 00726 } 00727 } else { 00728 res = monitor_dial(dial, chan); 00729 } 00730 00731 return res; 00732 }
| 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 1037 of file dial.c.
References ast_dial::actual_timeout, and ast_dial::timeout.
Referenced by page_exec().
01038 { 01039 dial->timeout = timeout; 01040 01041 if (dial->timeout > 0 && (dial->actual_timeout > dial->timeout || dial->actual_timeout == -1)) 01042 dial->actual_timeout = dial->timeout; 01043 01044 return; 01045 }
| 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 1027 of file dial.c.
References ast_dial::state_callback.
Referenced by sla_ring_station().
01028 { 01029 dial->state_callback = callback; 01030 }
| 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 1053 of file dial.c.
References ast_dial::actual_timeout, find_dial_channel(), and ast_dial_channel::timeout.
01054 { 01055 struct ast_dial_channel *channel = NULL; 01056 01057 if (!(channel = find_dial_channel(dial, num))) 01058 return; 01059 01060 channel->timeout = timeout; 01061 01062 if (channel->timeout > 0 && (dial->actual_timeout > channel->timeout || dial->actual_timeout == -1)) 01063 dial->actual_timeout = channel->timeout; 01064 01065 return; 01066 }
| enum ast_dial_result ast_dial_state | ( | struct ast_dial * | dial | ) |
Return state of dial.
| dial | Dialing structure |
Definition at line 769 of file dial.c.
References ast_dial::state.
Referenced by dial_trunk(), and sla_handle_dial_state_event().
00770 { 00771 return dial->state; 00772 }
| static void* async_dial | ( | void * | data | ) | [static] |
Dial async thread function.
Definition at line 684 of file dial.c.
References monitor_dial().
Referenced by ast_dial_run().
00685 { 00686 struct ast_dial *dial = data; 00687 00688 /* This is really really simple... we basically pass monitor_dial a NULL owner and it changes it's behavior */ 00689 monitor_dial(dial, NULL); 00690 00691 return NULL; 00692 }
| 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 311 of file dial.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, begin_dial_channel(), ast_dial::channels, and ast_dial_channel::list.
Referenced by ast_dial_run().
00312 { 00313 struct ast_dial_channel *channel = NULL; 00314 int success = 0; 00315 00316 /* Iterate through channel list, requesting and calling each one */ 00317 AST_LIST_LOCK(&dial->channels); 00318 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00319 success += begin_dial_channel(channel, chan); 00320 } 00321 AST_LIST_UNLOCK(&dial->channels); 00322 00323 /* If number of failures matches the number of channels, then this truly failed */ 00324 return success; 00325 }
| 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 ast_channel::accountcode, accountcode, ast_channel::adsicpe, ast_channel::appl, ast_call(), ast_channel_datastore_inherit(), 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, 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, ast_channel::language, 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 memset(&channel->owner->whentohangup, 0, sizeof(channel->owner->whentohangup)); 00270 00271 /* Inherit everything from he who spawned this dial */ 00272 if (chan) { 00273 ast_channel_inherit_variables(chan, channel->owner); 00274 ast_channel_datastore_inherit(chan, channel->owner); 00275 00276 /* Copy over callerid information */ 00277 S_REPLACE(channel->owner->cid.cid_num, ast_strdup(chan->cid.cid_num)); 00278 S_REPLACE(channel->owner->cid.cid_name, ast_strdup(chan->cid.cid_name)); 00279 S_REPLACE(channel->owner->cid.cid_ani, ast_strdup(chan->cid.cid_ani)); 00280 S_REPLACE(channel->owner->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis)); 00281 00282 ast_string_field_set(channel->owner, language, chan->language); 00283 ast_string_field_set(channel->owner, accountcode, chan->accountcode); 00284 channel->owner->cdrflags = chan->cdrflags; 00285 if (ast_strlen_zero(channel->owner->musicclass)) 00286 ast_string_field_set(channel->owner, musicclass, chan->musicclass); 00287 00288 channel->owner->cid.cid_pres = chan->cid.cid_pres; 00289 channel->owner->cid.cid_ton = chan->cid.cid_ton; 00290 channel->owner->cid.cid_tns = chan->cid.cid_tns; 00291 channel->owner->adsicpe = chan->adsicpe; 00292 channel->owner->transfercapability = chan->transfercapability; 00293 } 00294 00295 /* Attempt to actually call this device */ 00296 if ((res = ast_call(channel->owner, numsubst, 0))) { 00297 res = 0; 00298 ast_hangup(channel->owner); 00299 channel->owner = NULL; 00300 } else { 00301 if (chan) 00302 ast_poll_channel_add(chan, channel->owner); 00303 res = 1; 00304 ast_verb(3, "Called %s\n", numsubst); 00305 } 00306 00307 return res; 00308 }
| static struct ast_dial_channel* find_dial_channel | ( | struct ast_dial * | dial, | |
| int | num | |||
| ) | [static, read] |
Helper function for finding a channel in a dial structure based on number.
Definition at line 924 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().
00925 { 00926 struct ast_dial_channel *channel = AST_LIST_LAST(&dial->channels); 00927 00928 /* We can try to predict programmer behavior, the last channel they added is probably the one they wanted to modify */ 00929 if (channel->num == num) 00930 return channel; 00931 00932 /* Hrm not at the end... looking through the list it is! */ 00933 AST_LIST_LOCK(&dial->channels); 00934 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00935 if (channel->num == num) 00936 break; 00937 } 00938 AST_LIST_UNLOCK(&dial->channels); 00939 00940 return channel; 00941 }
| static struct ast_dial_channel* find_relative_dial_channel | ( | struct ast_dial * | dial, | |
| struct ast_channel * | owner | |||
| ) | [static, read] |
Helper function that finds the dialed channel based on owner.
Definition at line 367 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().
00368 { 00369 struct ast_dial_channel *channel = NULL; 00370 00371 AST_LIST_LOCK(&dial->channels); 00372 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00373 if (channel->owner == owner) 00374 break; 00375 } 00376 AST_LIST_UNLOCK(&dial->channels); 00377 00378 return channel; 00379 }
| 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 328 of file dial.c.
References AST_DIAL_OPTION_DISABLE_CALL_FORWARDING, ast_free, ast_hangup(), AST_LIST_UNLOCK, ast_strdup, begin_dial_channel(), ast_channel::call_forward, ast_dial::channels, ast_dial_channel::device, FIND_RELATIVE_OPTION, ast_dial_channel::owner, and ast_dial_channel::tech.
Referenced by monitor_dial().
00329 { 00330 struct ast_channel *original = channel->owner; 00331 char *tmp = ast_strdupa(channel->owner->call_forward); 00332 char *tech = "Local", *device = tmp, *stuff; 00333 00334 /* If call forwarding is disabled just drop the original channel and don't attempt to dial the new one */ 00335 if (FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_DISABLE_CALL_FORWARDING)) { 00336 ast_hangup(original); 00337 channel->owner = NULL; 00338 return 0; 00339 } 00340 00341 /* Figure out the new destination */ 00342 if ((stuff = strchr(tmp, '/'))) { 00343 *stuff++ = '\0'; 00344 tech = tmp; 00345 device = stuff; 00346 } 00347 00348 /* Drop old destination information */ 00349 ast_free(channel->tech); 00350 ast_free(channel->device); 00351 00352 /* Update the dial channel with the new destination information */ 00353 channel->tech = ast_strdup(tech); 00354 channel->device = ast_strdup(device); 00355 AST_LIST_UNLOCK(&dial->channels); 00356 00357 /* Finally give it a go... send it out into the world */ 00358 begin_dial_channel(channel, chan); 00359 00360 /* Drop the original channel */ 00361 ast_hangup(original); 00362 00363 return 0; 00364 }
| 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 390 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, 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().
00391 { 00392 if (fr->frametype == AST_FRAME_CONTROL) { 00393 switch (fr->subclass) { 00394 case AST_CONTROL_ANSWER: 00395 ast_verb(3, "%s answered %s\n", channel->owner->name, chan->name); 00396 AST_LIST_LOCK(&dial->channels); 00397 AST_LIST_REMOVE(&dial->channels, channel, list); 00398 AST_LIST_INSERT_HEAD(&dial->channels, channel, list); 00399 AST_LIST_UNLOCK(&dial->channels); 00400 set_state(dial, AST_DIAL_RESULT_ANSWERED); 00401 break; 00402 case AST_CONTROL_BUSY: 00403 ast_verb(3, "%s is busy\n", channel->owner->name); 00404 ast_hangup(channel->owner); 00405 channel->owner = NULL; 00406 break; 00407 case AST_CONTROL_CONGESTION: 00408 ast_verb(3, "%s is circuit-busy\n", channel->owner->name); 00409 ast_hangup(channel->owner); 00410 channel->owner = NULL; 00411 break; 00412 case AST_CONTROL_RINGING: 00413 ast_verb(3, "%s is ringing\n", channel->owner->name); 00414 if (!dial->options[AST_DIAL_OPTION_MUSIC]) 00415 ast_indicate(chan, AST_CONTROL_RINGING); 00416 set_state(dial, AST_DIAL_RESULT_RINGING); 00417 break; 00418 case AST_CONTROL_PROGRESS: 00419 ast_verb(3, "%s is making progress, passing it to %s\n", channel->owner->name, chan->name); 00420 ast_indicate(chan, AST_CONTROL_PROGRESS); 00421 set_state(dial, AST_DIAL_RESULT_PROGRESS); 00422 break; 00423 case AST_CONTROL_VIDUPDATE: 00424 ast_verb(3, "%s requested a video update, passing it to %s\n", channel->owner->name, chan->name); 00425 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 00426 break; 00427 case AST_CONTROL_SRCUPDATE: 00428 if (option_verbose > 2) 00429 ast_verbose (VERBOSE_PREFIX_3 "%s requested a source update, passing it to %s\n", channel->owner->name, chan->name); 00430 ast_indicate(chan, AST_CONTROL_SRCUPDATE); 00431 break; 00432 case AST_CONTROL_PROCEEDING: 00433 ast_verb(3, "%s is proceeding, passing it to %s\n", channel->owner->name, chan->name); 00434 ast_indicate(chan, AST_CONTROL_PROCEEDING); 00435 set_state(dial, AST_DIAL_RESULT_PROCEEDING); 00436 break; 00437 case AST_CONTROL_HOLD: 00438 ast_verb(3, "Call on %s placed on hold\n", chan->name); 00439 ast_indicate(chan, AST_CONTROL_HOLD); 00440 break; 00441 case AST_CONTROL_UNHOLD: 00442 ast_verb(3, "Call on %s left from hold\n", chan->name); 00443 ast_indicate(chan, AST_CONTROL_UNHOLD); 00444 break; 00445 case AST_CONTROL_OFFHOOK: 00446 case AST_CONTROL_FLASH: 00447 break; 00448 case -1: 00449 /* Prod the channel */ 00450 ast_indicate(chan, -1); 00451 break; 00452 default: 00453 break; 00454 } 00455 } 00456 00457 return; 00458 }
| 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 461 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().
00462 { 00463 /* If we have no owner we can only update the state of the dial structure, so only look at control frames */ 00464 if (fr->frametype != AST_FRAME_CONTROL) 00465 return; 00466 00467 switch (fr->subclass) { 00468 case AST_CONTROL_ANSWER: 00469 ast_verb(3, "%s answered\n", channel->owner->name); 00470 AST_LIST_LOCK(&dial->channels); 00471 AST_LIST_REMOVE(&dial->channels, channel, list); 00472 AST_LIST_INSERT_HEAD(&dial->channels, channel, list); 00473 AST_LIST_UNLOCK(&dial->channels); 00474 set_state(dial, AST_DIAL_RESULT_ANSWERED); 00475 break; 00476 case AST_CONTROL_BUSY: 00477 ast_verb(3, "%s is busy\n", channel->owner->name); 00478 ast_hangup(channel->owner); 00479 channel->owner = NULL; 00480 break; 00481 case AST_CONTROL_CONGESTION: 00482 ast_verb(3, "%s is circuit-busy\n", channel->owner->name); 00483 ast_hangup(channel->owner); 00484 channel->owner = NULL; 00485 break; 00486 case AST_CONTROL_RINGING: 00487 ast_verb(3, "%s is ringing\n", channel->owner->name); 00488 set_state(dial, AST_DIAL_RESULT_RINGING); 00489 break; 00490 case AST_CONTROL_PROGRESS: 00491 ast_verb(3, "%s is making progress\n", channel->owner->name); 00492 set_state(dial, AST_DIAL_RESULT_PROGRESS); 00493 break; 00494 case AST_CONTROL_PROCEEDING: 00495 ast_verb(3, "%s is proceeding\n", channel->owner->name); 00496 set_state(dial, AST_DIAL_RESULT_PROCEEDING); 00497 break; 00498 default: 00499 break; 00500 } 00501 00502 return; 00503 }
| 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 506 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().
00507 { 00508 struct ast_dial_channel *channel = NULL; 00509 int diff = ast_tvdiff_ms(ast_tvnow(), start), lowest_timeout = -1, new_timeout = -1; 00510 00511 /* If the global dial timeout tripped switch the state to timeout so our channel loop will drop every channel */ 00512 if (diff >= dial->timeout) { 00513 set_state(dial, AST_DIAL_RESULT_TIMEOUT); 00514 new_timeout = 0; 00515 } 00516 00517 /* Go through dropping out channels that have met their timeout */ 00518 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00519 if (dial->state == AST_DIAL_RESULT_TIMEOUT || diff >= channel->timeout) { 00520 ast_hangup(channel->owner); 00521 channel->owner = NULL; 00522 } else if ((lowest_timeout == -1) || (lowest_timeout > channel->timeout)) { 00523 lowest_timeout = channel->timeout; 00524 } 00525 } 00526 00527 /* Calculate the new timeout using the lowest timeout found */ 00528 if (lowest_timeout >= 0) 00529 new_timeout = lowest_timeout - diff; 00530 00531 return new_timeout; 00532 }
| 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 535 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_string_field_set, ast_strlen_zero(), ast_tvnow(), ast_waitfor_n(), ast_channel::call_forward, 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().
00536 { 00537 int timeout = -1; 00538 struct ast_channel *cs[AST_MAX_WATCHERS], *who = NULL; 00539 struct ast_dial_channel *channel = NULL; 00540 struct answer_exec_struct *answer_exec = NULL; 00541 struct timeval start; 00542 00543 set_state(dial, AST_DIAL_RESULT_TRYING); 00544 00545 /* If the "always indicate ringing" option is set, change state to ringing and indicate to the owner if present */ 00546 if (dial->options[AST_DIAL_OPTION_RINGING]) { 00547 set_state(dial, AST_DIAL_RESULT_RINGING); 00548 if (chan) 00549 ast_indicate(chan, AST_CONTROL_RINGING); 00550 } else if (chan && dial->options[AST_DIAL_OPTION_MUSIC] && 00551 !ast_strlen_zero(dial->options[AST_DIAL_OPTION_MUSIC])) { 00552 char *original_moh = ast_strdupa(chan->musicclass); 00553 ast_indicate(chan, -1); 00554 ast_string_field_set(chan, musicclass, dial->options[AST_DIAL_OPTION_MUSIC]); 00555 ast_moh_start(chan, dial->options[AST_DIAL_OPTION_MUSIC], NULL); 00556 ast_string_field_set(chan, musicclass, original_moh); 00557 } 00558 00559 /* Record start time for timeout purposes */ 00560 start = ast_tvnow(); 00561 00562 /* We actually figured out the maximum timeout we can do as they were added, so we can directly access the info */ 00563 timeout = dial->actual_timeout; 00564 00565 /* Go into an infinite loop while we are trying */ 00566 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)) { 00567 int pos = 0, count = 0; 00568 struct ast_frame *fr = NULL; 00569 00570 /* Set up channel structure array */ 00571 pos = count = 0; 00572 if (chan) 00573 cs[pos++] = chan; 00574 00575 /* Add channels we are attempting to dial */ 00576 AST_LIST_LOCK(&dial->channels); 00577 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00578 if (channel->owner) { 00579 cs[pos++] = channel->owner; 00580 count++; 00581 } 00582 } 00583 AST_LIST_UNLOCK(&dial->channels); 00584 00585 /* If we have no outbound channels in progress, switch state to unanswered and stop */ 00586 if (!count) { 00587 set_state(dial, AST_DIAL_RESULT_UNANSWERED); 00588 break; 00589 } 00590 00591 /* Just to be safe... */ 00592 if (dial->thread == AST_PTHREADT_STOP) 00593 break; 00594 00595 /* Wait for frames from channels */ 00596 who = ast_waitfor_n(cs, pos, &timeout); 00597 00598 /* Check to see if our thread is being cancelled */ 00599 if (dial->thread == AST_PTHREADT_STOP) 00600 break; 00601 00602 /* If the timeout no longer exists OR if we got no channel it basically means the timeout was tripped, so handle it */ 00603 if (!timeout || !who) { 00604 timeout = handle_timeout_trip(dial, start); 00605 continue; 00606 } 00607 00608 /* Find relative dial channel */ 00609 if (!chan || !IS_CALLER(chan, who)) 00610 channel = find_relative_dial_channel(dial, who); 00611 00612 /* See if this channel has been forwarded elsewhere */ 00613 if (!ast_strlen_zero(who->call_forward)) { 00614 handle_call_forward(dial, channel, chan); 00615 continue; 00616 } 00617 00618 /* Attempt to read in a frame */ 00619 if (!(fr = ast_read(who))) { 00620 /* If this is the caller then we switch state to hangup and stop */ 00621 if (chan && IS_CALLER(chan, who)) { 00622 set_state(dial, AST_DIAL_RESULT_HANGUP); 00623 break; 00624 } 00625 if (chan) 00626 ast_poll_channel_del(chan, channel->owner); 00627 ast_hangup(who); 00628 channel->owner = NULL; 00629 continue; 00630 } 00631 00632 /* Process the frame */ 00633 if (chan) 00634 handle_frame(dial, channel, fr, chan); 00635 else 00636 handle_frame_ownerless(dial, channel, fr); 00637 00638 /* Free the received frame and start all over */ 00639 ast_frfree(fr); 00640 } 00641 00642 /* Do post-processing from loop */ 00643 if (dial->state == AST_DIAL_RESULT_ANSWERED) { 00644 /* Hangup everything except that which answered */ 00645 AST_LIST_LOCK(&dial->channels); 00646 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00647 if (!channel->owner || channel->owner == who) 00648 continue; 00649 if (chan) 00650 ast_poll_channel_del(chan, channel->owner); 00651 ast_hangup(channel->owner); 00652 channel->owner = NULL; 00653 } 00654 AST_LIST_UNLOCK(&dial->channels); 00655 /* If ANSWER_EXEC is enabled as an option, execute application on answered channel */ 00656 if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC))) { 00657 channel->is_running_app = 1; 00658 answer_exec_run(dial, channel, answer_exec->app, answer_exec->args); 00659 channel->is_running_app = 0; 00660 } 00661 00662 if (chan && dial->options[AST_DIAL_OPTION_MUSIC] && 00663 !ast_strlen_zero(dial->options[AST_DIAL_OPTION_MUSIC])) { 00664 ast_moh_stop(chan); 00665 } 00666 } else if (dial->state == AST_DIAL_RESULT_HANGUP) { 00667 /* Hangup everything */ 00668 AST_LIST_LOCK(&dial->channels); 00669 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00670 if (!channel->owner) 00671 continue; 00672 if (chan) 00673 ast_poll_channel_del(chan, channel->owner); 00674 ast_hangup(channel->owner); 00675 channel->owner = NULL; 00676 } 00677 AST_LIST_UNLOCK(&dial->channels); 00678 } 00679 00680 return dial->state; 00681 }
| 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 381 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().
00382 { 00383 dial->state = state; 00384 00385 if (dial->state_callback) 00386 dial->state_callback(dial); 00387 }
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().
1.6.2