#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/linkedlists.h"
#include "asterisk/dial.h"
#include "asterisk/pbx.h"
Go to the source code of this file.
Data Structures | |
struct | answer_exec_struct |
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) |
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) |
static void * | answer_exec_enable (void *data) |
static void | answer_exec_run (struct ast_dial *dial, struct ast_dial_channel *dial_channel, char *app, char *args) |
struct ast_channel * | ast_dial_answered (struct ast_dial *dial) |
Return 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_state_callback (struct ast_dial *dial, ast_dial_state_callback callback) |
Set a callback for state changes. | |
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. | |
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 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 enum ast_dial_result | monitor_dial (struct ast_dial *dial, struct ast_channel *chan) |
Helper function that basically keeps tabs on dialing attempts. | |
static void | set_state (struct ast_dial *dial, enum ast_dial_result state) |
Variables | |
static struct ast_option_types | option_types [] |
Definition in file dial.c.
#define AST_MAX_WATCHERS 256 |
Maximum number of channels we can watch at a time.
Definition at line 168 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 171 of file dial.c.
Referenced by monitor_dial().
#define IS_CALLER | ( | chan, | |||
owner | ) | (chan == owner ? 1 : 0) |
Macro that determines whether a channel is the caller or not.
Definition at line 174 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] |
Definition at line 108 of file dial.c.
References answer_exec_struct::args, and free.
00109 { 00110 struct answer_exec_struct *answer_exec = data; 00111 00112 /* Make sure we have a value */ 00113 if (!answer_exec) 00114 return -1; 00115 00116 /* If arguments are present, free them too */ 00117 if (answer_exec->args) 00118 free(answer_exec->args); 00119 00120 /* This is simple - just free the structure */ 00121 free(answer_exec); 00122 00123 return 0; 00124 }
static void* answer_exec_enable | ( | void * | data | ) | [static] |
Definition at line 82 of file dial.c.
References answer_exec_struct::app, app, answer_exec_struct::args, ast_calloc, ast_strdup, ast_strdupa, and ast_strlen_zero().
00083 { 00084 struct answer_exec_struct *answer_exec = NULL; 00085 char *app = ast_strdupa((char*)data), *args = NULL; 00086 00087 /* Not giving any data to this option is bad, mmmk? */ 00088 if (ast_strlen_zero(app)) 00089 return NULL; 00090 00091 /* Create new data structure */ 00092 if (!(answer_exec = ast_calloc(1, sizeof(*answer_exec)))) 00093 return NULL; 00094 00095 /* Parse out application and arguments */ 00096 if ((args = strchr(app, '|'))) { 00097 *args++ = '\0'; 00098 answer_exec->args = ast_strdup(args); 00099 } 00100 00101 /* Copy application name */ 00102 ast_copy_string(answer_exec->app, app, sizeof(answer_exec->app)); 00103 00104 return answer_exec; 00105 }
static void answer_exec_run | ( | struct ast_dial * | dial, | |
struct ast_dial_channel * | dial_channel, | |||
char * | app, | |||
char * | args | |||
) | [static] |
Definition at line 127 of file dial.c.
References ast_hangup(), AST_PTHREADT_STOP, ast_dial_channel::owner, pbx_exec(), and pbx_findapp().
Referenced by monitor_dial().
00128 { 00129 struct ast_channel *chan = dial_channel->owner; 00130 struct ast_app *ast_app = pbx_findapp(app); 00131 00132 /* If the application was not found, return immediately */ 00133 if (!ast_app) 00134 return; 00135 00136 /* All is well... execute the application */ 00137 pbx_exec(chan, ast_app, args); 00138 00139 /* If another thread is not taking over hang up the channel */ 00140 if (dial->thread != AST_PTHREADT_STOP) { 00141 ast_hangup(chan); 00142 dial_channel->owner = NULL; 00143 } 00144 00145 return; 00146 }
struct ast_channel* ast_dial_answered | ( | struct ast_dial * | dial | ) | [read] |
Return channel that answered.
dial | Dialing structure |
Definition at line 594 of file dial.c.
References AST_DIAL_RESULT_ANSWERED, AST_LIST_FIRST, and ast_dial::state.
Referenced by dial_trunk(), and sla_handle_dial_state_event().
00595 { 00596 if (!dial) 00597 return NULL; 00598 00599 return ((dial->state == AST_DIAL_RESULT_ANSWERED) ? AST_LIST_FIRST(&dial->channels)->owner : NULL); 00600 }
int ast_dial_append | ( | struct ast_dial * | dial, | |
const char * | tech, | |||
const char * | device | |||
) |
Append a channel.
Definition at line 201 of file dial.c.
References ast_calloc, AST_LIST_INSERT_TAIL, ast_dial_channel::device, ast_dial::num, ast_dial_channel::num, and ast_dial_channel::tech.
Referenced by dial_trunk(), page_exec(), and sla_ring_station().
00202 { 00203 struct ast_dial_channel *channel = NULL; 00204 00205 /* Make sure we have required arguments */ 00206 if (!dial || !tech || !device) 00207 return -1; 00208 00209 /* Allocate new memory for dialed channel structure */ 00210 if (!(channel = ast_calloc(1, sizeof(*channel)))) 00211 return -1; 00212 00213 /* Record technology and device for when we actually dial */ 00214 channel->tech = tech; 00215 channel->device = device; 00216 00217 /* Grab reference number from dial structure */ 00218 channel->num = ast_atomic_fetchadd_int(&dial->num, +1); 00219 00220 /* Insert into channels list */ 00221 AST_LIST_INSERT_TAIL(&dial->channels, channel, list); 00222 00223 return channel->num; 00224 }
struct ast_dial* ast_dial_create | ( | void | ) | [read] |
New dialing structure.
Definition at line 180 of file dial.c.
References ast_calloc, AST_LIST_HEAD_INIT_NOLOCK, and AST_PTHREADT_NULL.
Referenced by dial_trunk(), page_exec(), and sla_ring_station().
00181 { 00182 struct ast_dial *dial = NULL; 00183 00184 /* Allocate new memory for structure */ 00185 if (!(dial = ast_calloc(1, sizeof(*dial)))) 00186 return NULL; 00187 00188 /* Initialize list of channels */ 00189 AST_LIST_HEAD_INIT_NOLOCK(&dial->channels); 00190 00191 /* Initialize thread to NULL */ 00192 dial->thread = AST_PTHREADT_NULL; 00193 00194 return dial; 00195 }
int ast_dial_destroy | ( | struct ast_dial * | dial | ) |
Destroys a dialing structure.
dial | Dialing structure to free |
Definition at line 675 of file dial.c.
References AST_DIAL_OPTION_MAX, ast_hangup(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_option_types::disable, free, option_types, ast_dial::options, ast_dial_channel::options, and ast_dial_channel::owner.
Referenced by dial_trunk(), page_exec(), run_station(), sla_hangup_stations(), sla_ring_station(), and sla_stop_ringing_station().
00676 { 00677 int i = 0; 00678 struct ast_dial_channel *channel = NULL; 00679 00680 if (!dial) 00681 return -1; 00682 00683 /* Hangup and deallocate all the dialed channels */ 00684 AST_LIST_TRAVERSE_SAFE_BEGIN(&dial->channels, channel, list) { 00685 /* Disable any enabled options */ 00686 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) { 00687 if (!channel->options[i]) 00688 continue; 00689 if (option_types[i].disable) 00690 option_types[i].disable(channel->options[i]); 00691 channel->options[i] = NULL; 00692 } 00693 /* Hang up channel if need be */ 00694 if (channel->owner) { 00695 ast_hangup(channel->owner); 00696 channel->owner = NULL; 00697 } 00698 /* Free structure */ 00699 AST_LIST_REMOVE_CURRENT(&dial->channels, list); 00700 free(channel); 00701 } 00702 AST_LIST_TRAVERSE_SAFE_END; 00703 00704 /* Disable any enabled options globally */ 00705 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) { 00706 if (!dial->options[i]) 00707 continue; 00708 if (option_types[i].disable) 00709 option_types[i].disable(dial->options[i]); 00710 dial->options[i] = NULL; 00711 } 00712 00713 /* Free structure */ 00714 free(dial); 00715 00716 return 0; 00717 }
void ast_dial_hangup | ( | struct ast_dial * | dial | ) |
Hangup channels.
dial | Dialing structure |
Definition at line 653 of file dial.c.
References ast_hangup(), AST_LIST_TRAVERSE, and ast_dial_channel::owner.
Referenced by ast_dial_run(), and page_exec().
00654 { 00655 struct ast_dial_channel *channel = NULL; 00656 00657 if (!dial) 00658 return; 00659 00660 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00661 if (channel->owner) { 00662 ast_hangup(channel->owner); 00663 channel->owner = NULL; 00664 } 00665 } 00666 00667 return; 00668 }
enum ast_dial_result ast_dial_join | ( | struct ast_dial * | dial | ) |
Cancel async thread.
dial | Dialing structure |
Definition at line 615 of file dial.c.
References ast_channel_lock, ast_channel_unlock, AST_DIAL_RESULT_FAILED, AST_LIST_FIRST, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, and ast_dial::state.
Referenced by dial_trunk(), page_exec(), run_station(), sla_hangup_stations(), sla_ring_station(), and sla_stop_ringing_station().
00616 { 00617 pthread_t thread; 00618 00619 /* If the dial structure is not running in async, return failed */ 00620 if (dial->thread == AST_PTHREADT_NULL) 00621 return AST_DIAL_RESULT_FAILED; 00622 00623 /* Record thread */ 00624 thread = dial->thread; 00625 00626 /* Stop the thread */ 00627 dial->thread = AST_PTHREADT_STOP; 00628 00629 /* If the answered channel is running an application we have to soft hangup it, can't just poke the thread */ 00630 if (AST_LIST_FIRST(&dial->channels)->is_running_app) { 00631 struct ast_channel *chan = AST_LIST_FIRST(&dial->channels)->owner; 00632 ast_channel_lock(chan); 00633 ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT); 00634 ast_channel_unlock(chan); 00635 } else { 00636 /* Now we signal it with SIGURG so it will break out of it's waitfor */ 00637 pthread_kill(thread, SIGURG); 00638 } 00639 00640 /* Finally wait for the thread to exit */ 00641 pthread_join(thread, NULL); 00642 00643 /* Yay thread is all gone */ 00644 dial->thread = AST_PTHREADT_NULL; 00645 00646 return dial->state; 00647 }
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 809 of file dial.c.
References AST_LIST_EMPTY, AST_LIST_LAST, AST_LIST_TRAVERSE, ast_option_types::disable, ast_dial_channel::num, option_types, and ast_dial_channel::options.
00810 { 00811 struct ast_dial_channel *channel = NULL; 00812 00813 /* Ensure we have required arguments */ 00814 if (!dial || AST_LIST_EMPTY(&dial->channels)) 00815 return -1; 00816 00817 /* Look for channel, we can sort of cheat and predict things - the last channel in the list will probably be what they want */ 00818 if (AST_LIST_LAST(&dial->channels)->num != num) { 00819 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00820 if (channel->num == num) 00821 break; 00822 } 00823 } else { 00824 channel = AST_LIST_LAST(&dial->channels); 00825 } 00826 00827 /* If none found, return failure */ 00828 if (!channel) 00829 return -1; 00830 00831 /* If the option is not enabled, return failure */ 00832 if (!channel->options[option]) 00833 return -1; 00834 00835 /* Execute callback of option to disable it if it exists */ 00836 if (option_types[option].disable) 00837 option_types[option].disable(channel->options[option]); 00838 00839 /* Finally disable the option on the structure */ 00840 channel->options[option] = NULL; 00841 00842 return 0; 00843 }
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 747 of file dial.c.
References AST_LIST_EMPTY, AST_LIST_LAST, AST_LIST_TRAVERSE, ast_option_types::enable, ast_dial_channel::num, option_types, and ast_dial_channel::options.
00748 { 00749 struct ast_dial_channel *channel = NULL; 00750 00751 /* Ensure we have required arguments */ 00752 if (!dial || AST_LIST_EMPTY(&dial->channels)) 00753 return -1; 00754 00755 /* Look for channel, we can sort of cheat and predict things - the last channel in the list will probably be what they want */ 00756 if (AST_LIST_LAST(&dial->channels)->num != num) { 00757 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00758 if (channel->num == num) 00759 break; 00760 } 00761 } else { 00762 channel = AST_LIST_LAST(&dial->channels); 00763 } 00764 00765 /* If none found, return failure */ 00766 if (!channel) 00767 return -1; 00768 00769 /* If the option is already enabled, return failure */ 00770 if (channel->options[option]) 00771 return -1; 00772 00773 /* Execute enable callback if it exists, if not simply make sure the value is set */ 00774 if (option_types[option].enable) 00775 channel->options[option] = option_types[option].enable(data); 00776 else 00777 channel->options[option] = (void*)1; 00778 00779 return 0; 00780 }
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 787 of file dial.c.
References ast_option_types::disable, option_types, and ast_dial::options.
00788 { 00789 /* If the option is not enabled, return failure */ 00790 if (!dial->options[option]) 00791 return -1; 00792 00793 /* Execute callback of option to disable if it exists */ 00794 if (option_types[option].disable) 00795 option_types[option].disable(dial->options[option]); 00796 00797 /* Finally disable option on the structure */ 00798 dial->options[option] = NULL; 00799 00800 return 0; 00801 }
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 725 of file dial.c.
References ast_option_types::enable, option_types, and ast_dial::options.
Referenced by page_exec().
00726 { 00727 /* If the option is already enabled, return failure */ 00728 if (dial->options[option]) 00729 return -1; 00730 00731 /* Execute enable callback if it exists, if not simply make sure the value is set */ 00732 if (option_types[option].enable) 00733 dial->options[option] = option_types[option].enable(data); 00734 else 00735 dial->options[option] = (void*)1; 00736 00737 return 0; 00738 }
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 554 of file dial.c.
References ast_dial_hangup(), AST_DIAL_RESULT_FAILED, AST_DIAL_RESULT_INVALID, AST_DIAL_RESULT_TRYING, AST_LIST_EMPTY, ast_log(), ast_pthread_create, async_dial(), begin_dial(), LOG_DEBUG, monitor_dial(), and ast_dial::state.
Referenced by dial_trunk(), page_exec(), and sla_ring_station().
00555 { 00556 enum ast_dial_result res = AST_DIAL_RESULT_TRYING; 00557 00558 /* Ensure required arguments are passed */ 00559 if (!dial || (!chan && !async)) { 00560 ast_log(LOG_DEBUG, "invalid #1\n"); 00561 return AST_DIAL_RESULT_INVALID; 00562 } 00563 00564 /* If there are no channels to dial we can't very well try to dial them */ 00565 if (AST_LIST_EMPTY(&dial->channels)) { 00566 ast_log(LOG_DEBUG, "invalid #2\n"); 00567 return AST_DIAL_RESULT_INVALID; 00568 } 00569 00570 /* Dial each requested channel */ 00571 if (!begin_dial(dial, chan)) 00572 return AST_DIAL_RESULT_FAILED; 00573 00574 /* If we are running async spawn a thread and send it away... otherwise block here */ 00575 if (async) { 00576 dial->state = AST_DIAL_RESULT_TRYING; 00577 /* Try to create a thread */ 00578 if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) { 00579 /* Failed to create the thread - hangup all dialed channels and return failed */ 00580 ast_dial_hangup(dial); 00581 res = AST_DIAL_RESULT_FAILED; 00582 } 00583 } else { 00584 res = monitor_dial(dial, chan); 00585 } 00586 00587 return res; 00588 }
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 845 of file dial.c.
References ast_dial::state_callback.
Referenced by sla_ring_station().
00846 { 00847 dial->state_callback = callback; 00848 }
enum ast_dial_result ast_dial_state | ( | struct ast_dial * | dial | ) |
Return state of dial.
dial | Dialing structure |
Definition at line 606 of file dial.c.
References ast_dial::state.
Referenced by dial_trunk(), and sla_handle_dial_state_event().
00607 { 00608 return dial->state; 00609 }
static void* async_dial | ( | void * | data | ) | [static] |
Dial async thread function.
Definition at line 540 of file dial.c.
References monitor_dial().
Referenced by ast_dial_run().
00541 { 00542 struct ast_dial *dial = data; 00543 00544 /* This is really really simple... we basically pass monitor_dial a NULL owner and it changes it's behavior */ 00545 monitor_dial(dial, NULL); 00546 00547 return NULL; 00548 }
static int begin_dial | ( | struct ast_dial * | dial, | |
struct ast_channel * | chan | |||
) | [static] |
Helper function that does the beginning dialing.
Definition at line 227 of file dial.c.
References accountcode, ast_channel::adsicpe, ast_channel::appl, ast_call(), ast_channel_inherit_variables(), AST_FORMAT_AUDIO_MASK, ast_hangup(), AST_LIST_TRAVERSE, AST_MAX_EXTENSION, ast_request(), ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_verbose(), 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, language, musicclass, ast_channel::nativeformats, option_verbose, ast_dial_channel::owner, S_REPLACE, ast_dial_channel::tech, ast_channel::transfercapability, VERBOSE_PREFIX_3, and ast_channel::whentohangup.
Referenced by ast_dial_run().
00228 { 00229 struct ast_dial_channel *channel = NULL; 00230 int success = 0, res = 0; 00231 00232 /* Iterate through channel list, requesting and calling each one */ 00233 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00234 char numsubst[AST_MAX_EXTENSION]; 00235 00236 /* Copy device string over */ 00237 ast_copy_string(numsubst, channel->device, sizeof(numsubst)); 00238 00239 /* Request that the channel be created */ 00240 if (!(channel->owner = ast_request(channel->tech, 00241 chan ? chan->nativeformats : AST_FORMAT_AUDIO_MASK, numsubst, &channel->cause))) { 00242 continue; 00243 } 00244 00245 channel->owner->appl = "AppDial2"; 00246 channel->owner->data = "(Outgoing Line)"; 00247 channel->owner->whentohangup = 0; 00248 00249 /* Inherit everything from he who spawned this Dial */ 00250 if (chan) { 00251 ast_channel_inherit_variables(chan, channel->owner); 00252 00253 /* Copy over callerid information */ 00254 S_REPLACE(channel->owner->cid.cid_num, ast_strdup(chan->cid.cid_num)); 00255 S_REPLACE(channel->owner->cid.cid_name, ast_strdup(chan->cid.cid_name)); 00256 S_REPLACE(channel->owner->cid.cid_ani, ast_strdup(chan->cid.cid_ani)); 00257 S_REPLACE(channel->owner->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis)); 00258 00259 ast_string_field_set(channel->owner, language, chan->language); 00260 ast_string_field_set(channel->owner, accountcode, chan->accountcode); 00261 channel->owner->cdrflags = chan->cdrflags; 00262 if (ast_strlen_zero(channel->owner->musicclass)) 00263 ast_string_field_set(channel->owner, musicclass, chan->musicclass); 00264 00265 channel->owner->cid.cid_pres = chan->cid.cid_pres; 00266 channel->owner->cid.cid_ton = chan->cid.cid_ton; 00267 channel->owner->cid.cid_tns = chan->cid.cid_tns; 00268 channel->owner->adsicpe = chan->adsicpe; 00269 channel->owner->transfercapability = chan->transfercapability; 00270 } 00271 00272 /* Actually call the device */ 00273 if ((res = ast_call(channel->owner, numsubst, 0))) { 00274 ast_hangup(channel->owner); 00275 channel->owner = NULL; 00276 } else { 00277 success++; 00278 if (option_verbose > 2) 00279 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst); 00280 } 00281 } 00282 00283 /* If number of failures matches the number of channels, then this truly failed */ 00284 return success; 00285 }
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 288 of file dial.c.
References AST_LIST_TRAVERSE, and ast_dial_channel::owner.
Referenced by monitor_dial().
00289 { 00290 struct ast_dial_channel *channel = NULL; 00291 00292 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00293 if (channel->owner == owner) 00294 break; 00295 } 00296 00297 return channel; 00298 }
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 309 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_UNHOLD, AST_CONTROL_VIDUPDATE, 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_REMOVE, ast_verbose(), ast_frame::frametype, option_verbose, ast_dial_channel::owner, set_state(), ast_frame::subclass, and VERBOSE_PREFIX_3.
Referenced by monitor_dial(), and socket_read().
00310 { 00311 if (fr->frametype == AST_FRAME_CONTROL) { 00312 switch (fr->subclass) { 00313 case AST_CONTROL_ANSWER: 00314 if (option_verbose > 2) 00315 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", channel->owner->name, chan->name); 00316 AST_LIST_REMOVE(&dial->channels, channel, list); 00317 AST_LIST_INSERT_HEAD(&dial->channels, channel, list); 00318 set_state(dial, AST_DIAL_RESULT_ANSWERED); 00319 break; 00320 case AST_CONTROL_BUSY: 00321 if (option_verbose > 2) 00322 ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", channel->owner->name); 00323 ast_hangup(channel->owner); 00324 channel->owner = NULL; 00325 break; 00326 case AST_CONTROL_CONGESTION: 00327 if (option_verbose > 2) 00328 ast_verbose(VERBOSE_PREFIX_3 "%s is circuit-busy\n", channel->owner->name); 00329 ast_hangup(channel->owner); 00330 channel->owner = NULL; 00331 break; 00332 case AST_CONTROL_RINGING: 00333 if (option_verbose > 2) 00334 ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", channel->owner->name); 00335 ast_indicate(chan, AST_CONTROL_RINGING); 00336 set_state(dial, AST_DIAL_RESULT_RINGING); 00337 break; 00338 case AST_CONTROL_PROGRESS: 00339 if (option_verbose > 2) 00340 ast_verbose (VERBOSE_PREFIX_3 "%s is making progress, passing it to %s\n", channel->owner->name, chan->name); 00341 ast_indicate(chan, AST_CONTROL_PROGRESS); 00342 set_state(dial, AST_DIAL_RESULT_PROGRESS); 00343 break; 00344 case AST_CONTROL_VIDUPDATE: 00345 if (option_verbose > 2) 00346 ast_verbose (VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", channel->owner->name, chan->name); 00347 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 00348 break; 00349 case AST_CONTROL_PROCEEDING: 00350 if (option_verbose > 2) 00351 ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding, passing it to %s\n", channel->owner->name, chan->name); 00352 ast_indicate(chan, AST_CONTROL_PROCEEDING); 00353 set_state(dial, AST_DIAL_RESULT_PROCEEDING); 00354 break; 00355 case AST_CONTROL_HOLD: 00356 if (option_verbose > 2) 00357 ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", chan->name); 00358 ast_indicate(chan, AST_CONTROL_HOLD); 00359 break; 00360 case AST_CONTROL_UNHOLD: 00361 if (option_verbose > 2) 00362 ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", chan->name); 00363 ast_indicate(chan, AST_CONTROL_UNHOLD); 00364 break; 00365 case AST_CONTROL_OFFHOOK: 00366 case AST_CONTROL_FLASH: 00367 break; 00368 case -1: 00369 /* Prod the channel */ 00370 ast_indicate(chan, -1); 00371 break; 00372 default: 00373 break; 00374 } 00375 } 00376 00377 return; 00378 }
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 381 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_REMOVE, ast_verbose(), ast_frame::frametype, option_verbose, ast_dial_channel::owner, set_state(), ast_frame::subclass, and VERBOSE_PREFIX_3.
Referenced by monitor_dial().
00382 { 00383 /* If we have no owner we can only update the state of the dial structure, so only look at control frames */ 00384 if (fr->frametype != AST_FRAME_CONTROL) 00385 return; 00386 00387 switch (fr->subclass) { 00388 case AST_CONTROL_ANSWER: 00389 if (option_verbose > 2) 00390 ast_verbose( VERBOSE_PREFIX_3 "%s answered\n", channel->owner->name); 00391 AST_LIST_REMOVE(&dial->channels, channel, list); 00392 AST_LIST_INSERT_HEAD(&dial->channels, channel, list); 00393 set_state(dial, AST_DIAL_RESULT_ANSWERED); 00394 break; 00395 case AST_CONTROL_BUSY: 00396 if (option_verbose > 2) 00397 ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", channel->owner->name); 00398 ast_hangup(channel->owner); 00399 channel->owner = NULL; 00400 break; 00401 case AST_CONTROL_CONGESTION: 00402 if (option_verbose > 2) 00403 ast_verbose(VERBOSE_PREFIX_3 "%s is circuit-busy\n", channel->owner->name); 00404 ast_hangup(channel->owner); 00405 channel->owner = NULL; 00406 break; 00407 case AST_CONTROL_RINGING: 00408 if (option_verbose > 2) 00409 ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", channel->owner->name); 00410 set_state(dial, AST_DIAL_RESULT_RINGING); 00411 break; 00412 case AST_CONTROL_PROGRESS: 00413 if (option_verbose > 2) 00414 ast_verbose (VERBOSE_PREFIX_3 "%s is making progress\n", channel->owner->name); 00415 set_state(dial, AST_DIAL_RESULT_PROGRESS); 00416 break; 00417 case AST_CONTROL_PROCEEDING: 00418 if (option_verbose > 2) 00419 ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding\n", channel->owner->name); 00420 set_state(dial, AST_DIAL_RESULT_PROCEEDING); 00421 break; 00422 default: 00423 break; 00424 } 00425 00426 return; 00427 }
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 430 of file dial.c.
References answer_exec_run(), answer_exec_struct::app, answer_exec_struct::args, AST_CONTROL_RINGING, AST_DIAL_OPTION_ANSWER_EXEC, 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_TRAVERSE, AST_MAX_WATCHERS, AST_PTHREADT_STOP, ast_read(), ast_waitfor_n(), find_relative_dial_channel(), FIND_RELATIVE_OPTION, handle_frame(), handle_frame_ownerless(), IS_CALLER, ast_dial_channel::is_running_app, ast_dial::options, ast_dial_channel::owner, set_state(), and ast_dial::state.
Referenced by ast_dial_run(), and async_dial().
00431 { 00432 int timeout = -1, count = 0; 00433 struct ast_channel *cs[AST_MAX_WATCHERS], *who = NULL; 00434 struct ast_dial_channel *channel = NULL; 00435 struct answer_exec_struct *answer_exec = NULL; 00436 00437 set_state(dial, AST_DIAL_RESULT_TRYING); 00438 00439 /* If the "always indicate ringing" option is set, change state to ringing and indicate to the owner if present */ 00440 if (dial->options[AST_DIAL_OPTION_RINGING]) { 00441 set_state(dial, AST_DIAL_RESULT_RINGING); 00442 if (chan) 00443 ast_indicate(chan, AST_CONTROL_RINGING); 00444 } 00445 00446 /* Go into an infinite loop while we are trying */ 00447 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)) { 00448 int pos = 0; 00449 struct ast_frame *fr = NULL; 00450 00451 /* Set up channel structure array */ 00452 pos = count = 0; 00453 if (chan) 00454 cs[pos++] = chan; 00455 00456 /* Add channels we are attempting to dial */ 00457 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00458 if (channel->owner) { 00459 cs[pos++] = channel->owner; 00460 count++; 00461 } 00462 } 00463 00464 /* If we have no outbound channels in progress, switch state to unanswered and stop */ 00465 if (!count) { 00466 set_state(dial, AST_DIAL_RESULT_UNANSWERED); 00467 break; 00468 } 00469 00470 /* Just to be safe... */ 00471 if (dial->thread == AST_PTHREADT_STOP) 00472 break; 00473 00474 /* Wait for frames from channels */ 00475 who = ast_waitfor_n(cs, pos, &timeout); 00476 00477 /* Check to see if our thread is being cancelled */ 00478 if (dial->thread == AST_PTHREADT_STOP) 00479 break; 00480 00481 /* If we are not being cancelled and we have no channel, then timeout was tripped */ 00482 if (!who) 00483 continue; 00484 00485 /* Find relative dial channel */ 00486 if (!chan || !IS_CALLER(chan, who)) 00487 channel = find_relative_dial_channel(dial, who); 00488 00489 /* Attempt to read in a frame */ 00490 if (!(fr = ast_read(who))) { 00491 /* If this is the caller then we switch state to hangup and stop */ 00492 if (chan && IS_CALLER(chan, who)) { 00493 set_state(dial, AST_DIAL_RESULT_HANGUP); 00494 break; 00495 } 00496 ast_hangup(who); 00497 channel->owner = NULL; 00498 continue; 00499 } 00500 00501 /* Process the frame */ 00502 if (chan) 00503 handle_frame(dial, channel, fr, chan); 00504 else 00505 handle_frame_ownerless(dial, channel, fr); 00506 00507 /* Free the received frame and start all over */ 00508 ast_frfree(fr); 00509 } 00510 00511 /* Do post-processing from loop */ 00512 if (dial->state == AST_DIAL_RESULT_ANSWERED) { 00513 /* Hangup everything except that which answered */ 00514 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00515 if (!channel->owner || channel->owner == who) 00516 continue; 00517 ast_hangup(channel->owner); 00518 channel->owner = NULL; 00519 } 00520 /* If ANSWER_EXEC is enabled as an option, execute application on answered channel */ 00521 if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC))) { 00522 channel->is_running_app = 1; 00523 answer_exec_run(dial, channel, answer_exec->app, answer_exec->args); 00524 channel->is_running_app = 0; 00525 } 00526 } else if (dial->state == AST_DIAL_RESULT_HANGUP) { 00527 /* Hangup everything */ 00528 AST_LIST_TRAVERSE(&dial->channels, channel, list) { 00529 if (!channel->owner) 00530 continue; 00531 ast_hangup(channel->owner); 00532 channel->owner = NULL; 00533 } 00534 } 00535 00536 return dial->state; 00537 }
static void set_state | ( | struct ast_dial * | dial, | |
enum ast_dial_result | state | |||
) | [static] |
Definition at line 300 of file dial.c.
References ast_dial::state, and ast_dial::state_callback.
Referenced by handle_frame(), handle_frame_ownerless(), and monitor_dial().
00301 { 00302 dial->state = state; 00303 00304 if (dial->state_callback) 00305 dial->state_callback(dial); 00306 }
struct ast_option_types option_types[] [static] |