Asterisk - The Open Source Telephony Project GIT-master-4f2b068
Loading...
Searching...
No Matches
Data Structures | Macros | Typedefs | Functions | Variables
dial.c File Reference

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"
#include "asterisk/app.h"
#include "asterisk/causes.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/max_forwards.h"
Include dependency graph for dial.c:

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
 

Macros

#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.
 

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_channelast_dial_answered (struct ast_dial *dial)
 Return channel that answered.
 
struct ast_channelast_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, const struct ast_assigned_ids *assignedids)
 Append a channel.
 
int ast_dial_append_channel (struct ast_dial *dial, struct ast_channel *chan)
 Append a channel using an actual channel object.
 
struct ast_dialast_dial_create (void)
 New dialing structure.
 
int ast_dial_destroy (struct ast_dial *dial)
 Destroys a dialing structure.
 
struct ast_channelast_dial_get_channel (struct ast_dial *dial, int num)
 Get the dialing channel, if prerun has been executed.
 
void * ast_dial_get_user_data (struct ast_dial *dial)
 Return the user data on a dial 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.
 
int ast_dial_prerun (struct ast_dial *dial, struct ast_channel *chan, struct ast_format_cap *cap)
 Request all appended channels, but do not dial.
 
int ast_dial_reason (struct ast_dial *dial, int num)
 Get the reason an outgoing channel has failed.
 
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.
 
void ast_dial_set_user_data (struct ast_dial *dial, void *user_data)
 Set user data on a dial structure.
 
enum ast_dial_result ast_dial_state (struct ast_dial *dial)
 Return state of dial.
 
const char * ast_hangup_cause_to_dial_status (int hangup_cause)
 Convert a hangup cause to a publishable dial status.
 
static void * async_dial (void *data)
 Dial async thread function.
 
static int begin_dial (struct ast_dial *dial, struct ast_channel *chan, int async)
 Helper function that does the beginning dialing per dial structure.
 
static int begin_dial_channel (struct ast_dial_channel *channel, struct ast_channel *chan, int async, const char *predial_string, struct ast_channel *forwarder_chan)
 Helper function that does the beginning dialing per-appended channel.
 
static int begin_dial_prerun (struct ast_dial_channel *channel, struct ast_channel *chan, struct ast_format_cap *cap, const char *predial_string)
 Helper function that requests all channels.
 
static int dial_append_common (struct ast_dial *dial, struct ast_dial_channel *channel, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
 
static struct ast_dial_channelfind_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_channelfind_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 frames.
 
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 int predial_disable (void *data)
 
static void * predial_enable (void *data)
 
static void set_state (struct ast_dial *dial, enum ast_dial_result state)
 

Variables

static const struct ast_option_types option_types []
 Map options to respective handlers (enable/disable).
 

Detailed Description

Dialing API.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file dial.c.

Macro Definition Documentation

◆ AST_MAX_WATCHERS

#define AST_MAX_WATCHERS   256

Maximum number of channels we can watch at a time.

Definition at line 211 of file dial.c.

◆ FIND_RELATIVE_OPTION

#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 214 of file dial.c.

◆ IS_CALLER

#define IS_CALLER (   chan,
  owner 
)    (chan == owner ? 1 : 0)

Macro that determines whether a channel is the caller or not.

Definition at line 217 of file dial.c.

Typedef Documentation

◆ ast_dial_option_cb_disable

typedef int(* ast_dial_option_cb_disable) (void *data)

Typedef for dial option disable.

Definition at line 81 of file dial.c.

◆ ast_dial_option_cb_enable

typedef void *(* ast_dial_option_cb_enable) (void *data)

Typedef for dial option enable.

Definition at line 78 of file dial.c.

Function Documentation

◆ answer_exec_disable()

static int answer_exec_disable ( void *  data)
static

Disable function for 'ANSWER_EXEC' option.

Definition at line 116 of file dial.c.

117{
118 struct answer_exec_struct *answer_exec = data;
119
120 /* Make sure we have a value */
121 if (!answer_exec)
122 return -1;
123
124 /* If arguments are present, free them too */
125 if (answer_exec->args)
126 ast_free(answer_exec->args);
127
128 /* This is simple - just free the structure */
129 ast_free(answer_exec);
130
131 return 0;
132}
#define ast_free(a)
Definition astmm.h:180
Structure for 'ANSWER_EXEC' option.
Definition dial.c:84
char * args
Definition dial.c:86

References answer_exec_struct::args, and ast_free.

◆ answer_exec_enable()

static void * answer_exec_enable ( void *  data)
static

Enable function for 'ANSWER_EXEC' option.

Definition at line 90 of file dial.c.

91{
92 struct answer_exec_struct *answer_exec = NULL;
93 char *app = ast_strdupa((char*)data), *args = NULL;
94
95 /* Not giving any data to this option is bad, mmmk? */
97 return NULL;
98
99 /* Create new data structure */
100 if (!(answer_exec = ast_calloc(1, sizeof(*answer_exec))))
101 return NULL;
102
103 /* Parse out application and arguments */
104 if ((args = strchr(app, ','))) {
105 *args++ = '\0';
106 answer_exec->args = ast_strdup(args);
107 }
108
109 /* Copy application name */
110 ast_copy_string(answer_exec->app, app, sizeof(answer_exec->app));
111
112 return answer_exec;
113}
static const char app[]
#define ast_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
static struct @522 args
#define NULL
Definition resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
char app[AST_MAX_APP]
Definition dial.c:85

References app, answer_exec_struct::app, answer_exec_struct::args, args, ast_calloc, ast_copy_string(), ast_strdup, ast_strdupa, ast_strlen_zero(), and NULL.

◆ answer_exec_run()

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 166 of file dial.c.

167{
168 struct ast_channel *chan = dial_channel->owner;
169
170 /* Execute the application, if available */
171 if (ast_pbx_exec_application(chan, app, args)) {
172 /* If the application was not found, return immediately */
173 return;
174 }
175
176 /* If another thread is not taking over hang up the channel */
177 ast_mutex_lock(&dial->lock);
178 if (dial->thread != AST_PTHREADT_STOP) {
179 ast_hangup(chan);
180 dial_channel->owner = NULL;
181 }
182 ast_mutex_unlock(&dial->lock);
183
184 return;
185}
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition channel.c:2538
#define AST_PTHREADT_STOP
Definition lock.h:74
#define ast_mutex_unlock(a)
Definition lock.h:197
#define ast_mutex_lock(a)
Definition lock.h:196
int ast_pbx_exec_application(struct ast_channel *chan, const char *app_name, const char *app_args)
Execute an application.
Definition pbx_app.c:501
Main Channel structure associated with a channel.
struct ast_channel * owner
Definition dial.c:73
pthread_t thread
Definition dial.c:57
ast_mutex_t lock
Definition dial.c:56

References app, args, ast_hangup(), ast_mutex_lock, ast_mutex_unlock, ast_pbx_exec_application(), AST_PTHREADT_STOP, ast_dial::lock, NULL, ast_dial_channel::owner, and ast_dial::thread.

Referenced by monitor_dial().

◆ ast_dial_answered()

struct ast_channel * ast_dial_answered ( struct ast_dial dial)

Return channel that answered.

Note
Returns the Asterisk channel that answered
Parameters
dialDialing structure

Definition at line 980 of file dial.c.

981{
982 if (!dial)
983 return NULL;
984
985 return ((dial->state == AST_DIAL_RESULT_ANSWERED) ? AST_LIST_FIRST(&dial->channels)->owner : NULL);
986}
@ AST_DIAL_RESULT_ANSWERED
Definition dial.h:61
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
enum ast_dial_result state
Definition dial.c:52
struct ast_dial::@369 channels

References AST_DIAL_RESULT_ANSWERED, AST_LIST_FIRST, ast_dial::channels, NULL, and ast_dial::state.

Referenced by ari_originate_dial(), dial_trunk(), page_state_callback(), and sla_handle_dial_state_event().

◆ ast_dial_answered_steal()

struct ast_channel * ast_dial_answered_steal ( struct ast_dial dial)

Steal the channel that answered.

Note
Returns the Asterisk channel that answered and removes it from the dialing structure
Parameters
dialDialing structure

Definition at line 992 of file dial.c.

993{
994 struct ast_channel *chan = NULL;
995
996 if (!dial)
997 return NULL;
998
999 if (dial->state == AST_DIAL_RESULT_ANSWERED) {
1000 chan = AST_LIST_FIRST(&dial->channels)->owner;
1001 AST_LIST_FIRST(&dial->channels)->owner = NULL;
1002 }
1003
1004 return chan;
1005}

References AST_DIAL_RESULT_ANSWERED, AST_LIST_FIRST, ast_dial::channels, NULL, and ast_dial::state.

Referenced by ari_originate_dial(), do_notify(), pbx_outgoing_exec(), and recall_callback().

◆ ast_dial_append()

int ast_dial_append ( struct ast_dial dial,
const char *  tech,
const char *  device,
const struct ast_assigned_ids assignedids 
)

Append a channel.

Note
Appends a channel to a dialing structure
Returns
Returns channel reference number on success, -1 on failure

Definition at line 280 of file dial.c.

281{
282 struct ast_dial_channel *channel = NULL;
283
284 /* Make sure we have required arguments */
285 if (!dial || !tech || !device)
286 return -1;
287
288 /* Allocate new memory for dialed channel structure */
289 if (!(channel = ast_calloc(1, sizeof(*channel))))
290 return -1;
291
292 return dial_append_common(dial, channel, tech, device, assignedids);
293}
static int dial_append_common(struct ast_dial *dial, struct ast_dial_channel *channel, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
Definition dial.c:247
Dialing channel structure. Contains per-channel dialing options, asterisk channel,...
Definition dial.c:63
char * tech
Definition dial.c:66
char * device
Definition dial.c:67

References ast_calloc, ast_dial_channel::device, dial_append_common(), NULL, and ast_dial_channel::tech.

Referenced by ari_channels_handle_originate_with_id(), dial_trunk(), do_notify(), page_exec(), pbx_outgoing_attempt(), recalling_enter(), and sla_ring_station().

◆ ast_dial_append_channel()

int ast_dial_append_channel ( struct ast_dial dial,
struct ast_channel chan 
)

Append a channel using an actual channel object.

Parameters
dialThe ast_dial to add the channel to
chanThe channel to add to the dial
Return values
-1Failure
non-zeroThe position of the channel in the list of dialed channels
Note
The chan ref is stolen with a successful return.

Definition at line 295 of file dial.c.

296{
297 struct ast_dial_channel *channel;
298 char *tech;
299 char *device;
300 char *dash;
301
302 if (!dial || !chan) {
303 return -1;
304 }
305
306 channel = ast_calloc(1, sizeof(*channel));
307 if (!channel) {
308 return -1;
309 }
310 channel->owner = chan;
311
313
314 device = strchr(tech, '/');
315 if (!device) {
316 ast_free(channel);
317 return -1;
318 }
319 *device++ = '\0';
320
321 dash = strrchr(device, '-');
322 if (dash) {
323 *dash = '\0';
324 }
325
326 return dial_append_common(dial, channel, tech, device, NULL);
327}
const char * ast_channel_name(const struct ast_channel *chan)

References ast_calloc, ast_channel_name(), ast_free, ast_strdupa, ast_dial_channel::device, dial_append_common(), NULL, ast_dial_channel::owner, and ast_dial_channel::tech.

◆ ast_dial_create()

struct ast_dial * ast_dial_create ( void  )

New dialing structure.

Note
Create a dialing structure
Returns
Returns a calloc'd ast_dial structure, NULL on failure

Definition at line 223 of file dial.c.

224{
225 struct ast_dial *dial = NULL;
226
227 /* Allocate new memory for structure */
228 if (!(dial = ast_calloc(1, sizeof(*dial))))
229 return NULL;
230
231 /* Initialize list of channels */
233
234 /* Initialize thread to NULL */
236
237 /* No timeout exists... yet */
238 dial->timeout = -1;
239 dial->actual_timeout = -1;
240
241 /* Can't forget about the lock */
242 ast_mutex_init(&dial->lock);
243
244 return dial;
245}
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define AST_PTHREADT_NULL
Definition lock.h:73
#define ast_mutex_init(pmutex)
Definition lock.h:193
Main dialing structure. Contains global options, channels being dialed, and more!
Definition dial.c:48
int timeout
Definition dial.c:50
int actual_timeout
Definition dial.c:51

References ast_dial::actual_timeout, ast_calloc, AST_LIST_HEAD_INIT, ast_mutex_init, AST_PTHREADT_NULL, ast_dial::channels, ast_dial::lock, NULL, ast_dial::thread, and ast_dial::timeout.

Referenced by ari_channels_handle_originate_with_id(), dial_trunk(), do_notify(), page_exec(), pbx_outgoing_attempt(), recalling_enter(), and sla_ring_station().

◆ ast_dial_destroy()

int ast_dial_destroy ( struct ast_dial dial)

Destroys a dialing structure.

Note
Cancels dialing and destroys (free's) the given ast_dial structure
Parameters
dialDialing structure to free
Return values
0on success
-1on failure

Definition at line 1094 of file dial.c.

1095{
1096 int i = 0;
1097 struct ast_dial_channel *channel = NULL;
1098
1099 if (!dial)
1100 return -1;
1101
1102 /* Hangup and deallocate all the dialed channels */
1103 AST_LIST_LOCK(&dial->channels);
1104 AST_LIST_TRAVERSE_SAFE_BEGIN(&dial->channels, channel, list) {
1105 /* Disable any enabled options */
1106 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
1107 if (!channel->options[i])
1108 continue;
1109 if (option_types[i].disable)
1110 option_types[i].disable(channel->options[i]);
1111 channel->options[i] = NULL;
1112 }
1113
1114 /* Hang up channel if need be */
1115 ast_hangup(channel->owner);
1116 channel->owner = NULL;
1117
1118 /* Free structure */
1119 ast_free(channel->tech);
1120 ast_free(channel->device);
1121 ast_free(channel->assignedid1);
1122 ast_free(channel->assignedid2);
1123
1125 ast_free(channel);
1126 }
1128 AST_LIST_UNLOCK(&dial->channels);
1129
1130 /* Disable any enabled options globally */
1131 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
1132 if (!dial->options[i])
1133 continue;
1134 if (option_types[i].disable)
1135 option_types[i].disable(dial->options[i]);
1136 dial->options[i] = NULL;
1137 }
1138
1139 /* Lock be gone! */
1140 ast_mutex_destroy(&dial->lock);
1141
1142 /* Free structure */
1143 ast_free(dial);
1144
1145 return 0;
1146}
static const struct ast_option_types option_types[]
Map options to respective handlers (enable/disable).
Definition dial.c:199
@ AST_DIAL_OPTION_MAX
Definition dial.h:50
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_LOCK(head)
Locks a list.
Definition linkedlists.h:40
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define ast_mutex_destroy(a)
Definition lock.h:195
struct ast_dial_channel::@370 list
char * assignedid2
Definition dial.c:72
void * options[AST_DIAL_OPTION_MAX]
Definition dial.c:68
char * assignedid1
Definition dial.c:71
void * options[AST_DIAL_OPTION_MAX]
Definition dial.c:53
ast_dial_option_cb_disable disable
Definition dial.c:190

References ast_dial_channel::assignedid1, ast_dial_channel::assignedid2, 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, NULL, option_types, ast_dial::options, ast_dial_channel::options, ast_dial_channel::owner, and ast_dial_channel::tech.

Referenced by ari_channels_handle_originate_with_id(), ari_originate_dial(), dial_trunk(), do_notify(), monitor_dial(), page_exec(), pbx_outgoing_destroy(), recalling_exit(), run_station(), sla_handle_dial_state_event(), sla_hangup_stations(), sla_ring_station(), and sla_stop_ringing_station().

◆ ast_dial_get_channel()

struct ast_channel * ast_dial_get_channel ( struct ast_dial dial,
int  num 
)

Get the dialing channel, if prerun has been executed.

Parameters
dialDial structure
numChannel number to get channel of
Returns
Pointer to channel, without reference

Definition at line 1261 of file dial.c.

1262{
1263 struct ast_dial_channel *channel;
1264
1265 if (!dial || AST_LIST_EMPTY(&dial->channels) || !(channel = find_dial_channel(dial, num))) {
1266 return NULL;
1267 }
1268
1269 return channel->owner;
1270}
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.
Definition dial.c:1165
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.

References AST_LIST_EMPTY, ast_dial::channels, find_dial_channel(), NULL, ast_dial_channel::num, and ast_dial_channel::owner.

Referenced by ari_channels_handle_originate_with_id(), pbx_outgoing_attempt(), pbx_outgoing_state_callback(), and recalling_enter().

◆ ast_dial_get_user_data()

void * ast_dial_get_user_data ( struct ast_dial dial)

Return the user data on a dial structure.

Parameters
dialThe dial structure

Definition at line 1282 of file dial.c.

1283{
1284 return dial->user_data;
1285}
void * user_data
Definition dial.c:55

References ast_dial::user_data.

Referenced by ari_originate_dial(), page_state_callback(), and recall_callback().

◆ ast_dial_hangup()

void ast_dial_hangup ( struct ast_dial dial)

Hangup channels.

Note
Hangup all active channels
Parameters
dialDialing structure

Definition at line 1077 of file dial.c.

1078{
1079 struct ast_dial_channel *channel = NULL;
1080
1081 if (!dial)
1082 return;
1083
1084 AST_LIST_LOCK(&dial->channels);
1085 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
1086 ast_hangup(channel->owner);
1087 channel->owner = NULL;
1088 }
1089 AST_LIST_UNLOCK(&dial->channels);
1090
1091 return;
1092}
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.

References ast_hangup(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_dial::channels, ast_dial_channel::list, NULL, and ast_dial_channel::owner.

Referenced by ast_dial_run(), and page_exec().

◆ ast_dial_join()

enum ast_dial_result ast_dial_join ( struct ast_dial dial)

Cancel async thread.

Note
Cancel a running async thread
Parameters
dialDialing structure

Definition at line 1020 of file dial.c.

1021{
1022 pthread_t thread;
1023
1024 /* If the dial structure is not running in async, return failed */
1025 if (dial->thread == AST_PTHREADT_NULL)
1027
1028 /* Record thread */
1029 thread = dial->thread;
1030
1031 /* Boom, commence locking */
1032 ast_mutex_lock(&dial->lock);
1033
1034 /* Stop the thread */
1035 dial->thread = AST_PTHREADT_STOP;
1036
1037 /* If the answered channel is running an application we have to soft hangup it, can't just poke the thread */
1038 AST_LIST_LOCK(&dial->channels);
1039 if (AST_LIST_FIRST(&dial->channels)->is_running_app) {
1040 struct ast_channel *chan = AST_LIST_FIRST(&dial->channels)->owner;
1041 if (chan) {
1042 ast_channel_lock(chan);
1044 ast_channel_unlock(chan);
1045 }
1046 } else {
1047 struct ast_dial_channel *channel = NULL;
1048
1049 /* Now we signal it with SIGURG so it will break out of it's waitfor */
1050 pthread_kill(thread, SIGURG);
1051
1052 /* pthread_kill may not be enough, if outgoing channel has already got an answer (no more in waitfor) but is not yet running an application. Force soft hangup. */
1053 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
1054 if (channel->owner) {
1056 }
1057 }
1058 }
1059 AST_LIST_UNLOCK(&dial->channels);
1060
1061 /* Yay done with it */
1062 ast_mutex_unlock(&dial->lock);
1063
1064 /* Finally wait for the thread to exit */
1065 pthread_join(thread, NULL);
1066
1067 /* Yay thread is all gone */
1068 dial->thread = AST_PTHREADT_NULL;
1069
1070 return dial->state;
1071}
pthread_t thread
Definition app_sla.c:335
#define ast_channel_lock(chan)
Definition channel.h:2982
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition channel.c:2461
@ AST_SOFTHANGUP_EXPLICIT
Definition channel.h:1168
#define ast_channel_unlock(chan)
Definition channel.h:2983
@ AST_DIAL_RESULT_FAILED
Definition dial.h:56

References ast_channel_lock, ast_channel_unlock, AST_DIAL_RESULT_FAILED, AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_dial::channels, ast_dial_channel::list, ast_dial::lock, NULL, ast_dial_channel::owner, ast_dial::state, thread, and ast_dial::thread.

Referenced by dial_trunk(), page_exec(), recalling_exit(), run_station(), sla_handle_dial_state_event(), sla_hangup_stations(), sla_ring_station(), and sla_stop_ringing_station().

◆ ast_dial_option_disable()

int ast_dial_option_disable ( struct ast_dial dial,
int  num,
enum ast_dial_option  option 
)

Disables an option per channel.

Parameters
dialDial structure
numChannel number to disable option on
optionOption to disable
Return values
0on success
-1on failure

Definition at line 1225 of file dial.c.

1226{
1227 struct ast_dial_channel *channel = NULL;
1228
1229 /* Ensure we have required arguments */
1230 if (!dial || AST_LIST_EMPTY(&dial->channels))
1231 return -1;
1232
1233 if (!(channel = find_dial_channel(dial, num)))
1234 return -1;
1235
1236 /* If the option is not enabled, return failure */
1237 if (!channel->options[option])
1238 return -1;
1239
1240 /* Execute callback of option to disable it if it exists */
1241 if (option_types[option].disable)
1242 option_types[option].disable(channel->options[option]);
1243
1244 /* Finally disable the option on the structure */
1245 channel->options[option] = NULL;
1246
1247 return 0;
1248}

References AST_LIST_EMPTY, ast_dial::channels, ast_option_types::disable, find_dial_channel(), NULL, ast_dial_channel::num, option_types, and ast_dial_channel::options.

◆ ast_dial_option_enable()

int ast_dial_option_enable ( struct ast_dial dial,
int  num,
enum ast_dial_option  option,
void *  data 
)

Enables an option per channel.

Parameters
dialDial structure
numChannel number to enable option on
optionOption to enable
dataData to pass to this option (not always needed)
Return values
0on success
-1on failure

Definition at line 1184 of file dial.c.

1185{
1186 struct ast_dial_channel *channel = NULL;
1187
1188 /* Ensure we have required arguments */
1189 if (!dial || AST_LIST_EMPTY(&dial->channels))
1190 return -1;
1191
1192 if (!(channel = find_dial_channel(dial, num)))
1193 return -1;
1194
1195 /* If the option is already enabled, return failure */
1196 if (channel->options[option])
1197 return -1;
1198
1199 /* Execute enable callback if it exists, if not simply make sure the value is set */
1200 if (option_types[option].enable)
1201 channel->options[option] = option_types[option].enable(data);
1202 else
1203 channel->options[option] = (void*)1;
1204
1205 return 0;
1206}
ast_dial_option_cb_enable enable
Definition dial.c:189

References AST_LIST_EMPTY, ast_dial::channels, ast_option_types::enable, find_dial_channel(), NULL, ast_dial_channel::num, option_types, and ast_dial_channel::options.

◆ ast_dial_option_global_disable()

int ast_dial_option_global_disable ( struct ast_dial dial,
enum ast_dial_option  option 
)

Disables an option globally.

Parameters
dialDial structure to disable option on
optionOption to disable
Return values
0on success
-1on failure

Definition at line 1208 of file dial.c.

1209{
1210 /* If the option is not enabled, return failure */
1211 if (!dial->options[option]) {
1212 return -1;
1213 }
1214
1215 /* Execute callback of option to disable if it exists */
1216 if (option_types[option].disable)
1217 option_types[option].disable(dial->options[option]);
1218
1219 /* Finally disable option on the structure */
1220 dial->options[option] = NULL;
1221
1222 return 0;
1223}

References ast_option_types::disable, NULL, option_types, and ast_dial::options.

◆ ast_dial_option_global_enable()

int ast_dial_option_global_enable ( struct ast_dial dial,
enum ast_dial_option  option,
void *  data 
)

Enables an option globally.

Parameters
dialDial structure to enable option on
optionOption to enable
dataData to pass to this option (not always needed)
Return values
0on success
-1on failure

Definition at line 1148 of file dial.c.

1149{
1150 /* If the option is already enabled, return failure */
1151 if (dial->options[option])
1152 return -1;
1153
1154 /* Execute enable callback if it exists, if not simply make sure the value is set */
1155 if (option_types[option].enable)
1156 dial->options[option] = option_types[option].enable(data);
1157 else
1158 dial->options[option] = (void*)1;
1159
1160 return 0;
1161}

References ast_option_types::enable, option_types, and ast_dial::options.

Referenced by do_notify(), page_exec(), and pbx_outgoing_attempt().

◆ ast_dial_prerun()

int ast_dial_prerun ( struct ast_dial dial,
struct ast_channel chan,
struct ast_format_cap cap 
)

Request all appended channels, but do not dial.

Parameters
dialDialing structure
chanOptional dialing channel
capOptional requested capabilities
Return values
-1failure
0success

Definition at line 431 of file dial.c.

432{
433 struct ast_dial_channel *channel;
434 int res = -1;
435 char *predial_string = dial->options[AST_DIAL_OPTION_PREDIAL];
436
437 AST_LIST_LOCK(&dial->channels);
438 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
439 if ((res = begin_dial_prerun(channel, chan, cap, predial_string))) {
440 break;
441 }
442 }
444
445 return res;
446}
static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channel *chan, struct ast_format_cap *cap, const char *predial_string)
Helper function that requests all channels.
Definition dial.c:330
@ AST_DIAL_OPTION_PREDIAL
Definition dial.h:47

References AST_DIAL_OPTION_PREDIAL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, begin_dial_prerun(), ast_dial::channels, ast_dial_channel::list, and ast_dial::options.

Referenced by ari_channels_handle_originate_with_id(), pbx_outgoing_attempt(), and recalling_enter().

◆ ast_dial_reason()

int ast_dial_reason ( struct ast_dial dial,
int  num 
)

Get the reason an outgoing channel has failed.

Parameters
dialDial structure
numChannel number to get the reason from
Returns
Numerical cause code

Definition at line 1250 of file dial.c.

1251{
1252 struct ast_dial_channel *channel;
1253
1254 if (!dial || AST_LIST_EMPTY(&dial->channels) || !(channel = find_dial_channel(dial, num))) {
1255 return -1;
1256 }
1257
1258 return channel->cause;
1259}

References AST_LIST_EMPTY, ast_dial_channel::cause, ast_dial::channels, find_dial_channel(), and ast_dial_channel::num.

Referenced by pbx_outgoing_attempt().

◆ ast_dial_run()

enum ast_dial_result ast_dial_run ( struct ast_dial dial,
struct ast_channel chan,
int  async 
)

Execute dialing synchronously or asynchronously.

Note
Dials channels in a dial structure.
Returns
Returns dial result code. (TRYING/INVALID/FAILED/ANSWERED/TIMEOUT/UNANSWERED).

Definition at line 938 of file dial.c.

939{
941
942 /* Ensure required arguments are passed */
943 if (!dial) {
944 ast_debug(1, "invalid #1\n");
946 }
947
948 /* If there are no channels to dial we can't very well try to dial them */
949 if (AST_LIST_EMPTY(&dial->channels)) {
950 ast_debug(1, "invalid #2\n");
952 }
953
954 /* Dial each requested channel */
955 if (!begin_dial(dial, chan, async))
957
958 /* If we are running async spawn a thread and send it away... otherwise block here */
959 if (async) {
960 /* reference be released at dial destruction if it isn't NULL */
963 /* Try to create a thread */
964 if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) {
965 /* Failed to create the thread - hangup all dialed channels and return failed */
966 ast_dial_hangup(dial);
968 }
969 } else {
970 res = monitor_dial(dial, chan);
971 }
972
973 return res;
974}
static void * async_dial(void *data)
Dial async thread function.
Definition dial.c:921
void ast_dial_hangup(struct ast_dial *dial)
Hangup channels.
Definition dial.c:1077
static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_channel *chan)
Helper function that basically keeps tabs on dialing attempts.
Definition dial.c:769
static int begin_dial(struct ast_dial *dial, struct ast_channel *chan, int async)
Helper function that does the beginning dialing per dial structure.
Definition dial.c:481
ast_dial_result
List of return codes for dial run API calls.
Definition dial.h:54
@ AST_DIAL_RESULT_INVALID
Definition dial.h:55
@ AST_DIAL_RESULT_TRYING
Definition dial.h:57
#define ast_debug(level,...)
Log a DEBUG message.
ast_callid ast_read_threadstorage_callid(void)
extracts the callid from the thread
Definition logger.c:2268
ast_callid callid
Definition dial.c:58
#define ast_pthread_create(a, b, c, d)
Definition utils.h:624

References ast_debug, ast_dial_hangup(), AST_DIAL_RESULT_FAILED, AST_DIAL_RESULT_INVALID, AST_DIAL_RESULT_TRYING, AST_LIST_EMPTY, ast_pthread_create, ast_read_threadstorage_callid(), async_dial(), begin_dial(), ast_dial::callid, ast_dial::channels, monitor_dial(), NULL, ast_dial::state, and ast_dial::thread.

Referenced by ari_originate_dial(), dial_trunk(), do_notify(), page_exec(), pbx_outgoing_exec(), recalling_enter(), and sla_ring_station().

◆ ast_dial_set_global_timeout()

void ast_dial_set_global_timeout ( struct ast_dial dial,
int  timeout 
)

Set the maximum time (globally) allowed for trying to ring phones.

Parameters
dialThe dial structure to apply the time limit to
timeoutMaximum time allowed in milliseconds

Definition at line 1287 of file dial.c.

1288{
1289 dial->timeout = timeout;
1290
1291 if (dial->timeout > 0 && (dial->actual_timeout > dial->timeout || dial->actual_timeout == -1))
1292 dial->actual_timeout = dial->timeout;
1293
1294 return;
1295}

References ast_dial::actual_timeout, ast_dial::timeout, and ast_dial_channel::timeout.

Referenced by ari_channels_handle_originate_with_id(), do_notify(), page_exec(), and pbx_outgoing_attempt().

◆ ast_dial_set_state_callback()

void ast_dial_set_state_callback ( struct ast_dial dial,
ast_dial_state_callback  callback 
)

Set a callback for state changes.

Parameters
dialThe dial structure to watch for state changes
callbackthe callback

Definition at line 1272 of file dial.c.

1273{
1274 dial->state_callback = callback;
1275}
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags, int rdlock)
ast_dial_state_callback state_callback
Definition dial.c:54

References callback(), and ast_dial::state_callback.

Referenced by page_exec(), pbx_outgoing_attempt(), recalling_enter(), and sla_ring_station().

◆ ast_dial_set_timeout()

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.

Parameters
dialThe dial structure the channel belongs to
numChannel number to set timeout on
timeoutMaximum time allowed in milliseconds

Definition at line 1297 of file dial.c.

1298{
1299 struct ast_dial_channel *channel = NULL;
1300
1301 if (!(channel = find_dial_channel(dial, num)))
1302 return;
1303
1304 channel->timeout = timeout;
1305
1306 if (channel->timeout > 0 && (dial->actual_timeout > channel->timeout || dial->actual_timeout == -1))
1307 dial->actual_timeout = channel->timeout;
1308
1309 return;
1310}

References ast_dial::actual_timeout, find_dial_channel(), NULL, ast_dial_channel::num, and ast_dial_channel::timeout.

◆ ast_dial_set_user_data()

void ast_dial_set_user_data ( struct ast_dial dial,
void *  user_data 
)

Set user data on a dial structure.

Parameters
dialThe dial structure to set a user data pointer on
user_dataThe user data pointer

Definition at line 1277 of file dial.c.

1278{
1279 dial->user_data = user_data;
1280}

References ast_dial::user_data.

Referenced by ari_channels_handle_originate_with_id(), page_exec(), and recalling_enter().

◆ ast_dial_state()

enum ast_dial_result ast_dial_state ( struct ast_dial dial)

Return state of dial.

Note
Returns the state of the dial attempt
Parameters
dialDialing structure

Definition at line 1011 of file dial.c.

1012{
1013 return dial->state;
1014}

References ast_dial::state.

Referenced by dial_trunk(), page_state_callback(), pbx_outgoing_state_callback(), recall_callback(), and sla_handle_dial_state_event().

◆ ast_hangup_cause_to_dial_status()

const char * ast_hangup_cause_to_dial_status ( int  hangup_cause)

Convert a hangup cause to a publishable dial status.

Since
12

Definition at line 752 of file dial.c.

753{
754 switch(hangup_cause) {
755 case AST_CAUSE_BUSY:
756 return "BUSY";
758 return "CONGESTION";
761 return "CHANUNAVAIL";
763 default:
764 return "NOANSWER";
765 }
766}
#define AST_CAUSE_CONGESTION
Definition causes.h:153
#define AST_CAUSE_NO_ROUTE_DESTINATION
Definition causes.h:100
#define AST_CAUSE_UNREGISTERED
Definition causes.h:154
#define AST_CAUSE_BUSY
Definition causes.h:149
#define AST_CAUSE_NO_ANSWER
Definition causes.h:109

References AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_ROUTE_DESTINATION, and AST_CAUSE_UNREGISTERED.

Referenced by monitor_dial(), try_calling(), and wait_for_answer().

◆ async_dial()

static void * async_dial ( void *  data)
static

Dial async thread function.

Definition at line 921 of file dial.c.

922{
923 struct ast_dial *dial = data;
924 if (dial->callid) {
926 }
927
928 /* This is really really simple... we basically pass monitor_dial a NULL owner and it changes it's behavior */
929 monitor_dial(dial, NULL);
930
931 return NULL;
932}
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition logger.c:2290

References ast_callid_threadassoc_add(), ast_dial::callid, monitor_dial(), and NULL.

Referenced by ast_dial_run().

◆ begin_dial()

static int begin_dial ( struct ast_dial dial,
struct ast_channel chan,
int  async 
)
static

Helper function that does the beginning dialing per dial structure.

Definition at line 481 of file dial.c.

482{
483 struct ast_dial_channel *channel = NULL;
484 int success = 0;
485 char *predial_string = dial->options[AST_DIAL_OPTION_PREDIAL];
486
487 /* Iterate through channel list, requesting and calling each one */
488 AST_LIST_LOCK(&dial->channels);
489 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
490 success += begin_dial_channel(channel, chan, async, predial_string, NULL);
491 }
493
494 /* If number of failures matches the number of channels, then this truly failed */
495 return success;
496}
static int begin_dial_channel(struct ast_dial_channel *channel, struct ast_channel *chan, int async, const char *predial_string, struct ast_channel *forwarder_chan)
Helper function that does the beginning dialing per-appended channel.
Definition dial.c:449

References AST_DIAL_OPTION_PREDIAL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, begin_dial_channel(), ast_dial::channels, ast_dial_channel::list, NULL, and ast_dial::options.

Referenced by ast_dial_run().

◆ begin_dial_channel()

static int begin_dial_channel ( struct ast_dial_channel channel,
struct ast_channel chan,
int  async,
const char *  predial_string,
struct ast_channel forwarder_chan 
)
static

Helper function that does the beginning dialing per-appended channel.

Definition at line 449 of file dial.c.

450{
451 int res = 1;
452 char forwarder[AST_CHANNEL_NAME];
453
454 /* If no owner channel exists yet execute pre-run */
455 if (!channel->owner && begin_dial_prerun(channel, chan, NULL, predial_string)) {
456 return 0;
457 }
458
459 if (forwarder_chan) {
460 ast_copy_string(forwarder, ast_channel_name(forwarder_chan), sizeof(forwarder));
461 ast_channel_lock(channel->owner);
462 pbx_builtin_setvar_helper(channel->owner, "FORWARDERNAME", forwarder);
463 ast_channel_unlock(channel->owner);
464 }
465
466 /* Attempt to actually call this device */
467 if ((res = ast_call(channel->owner, channel->device, 0))) {
468 res = 0;
469 ast_hangup(channel->owner);
470 channel->owner = NULL;
471 } else {
472 ast_channel_publish_dial(async ? NULL : chan, channel->owner, channel->device, NULL);
473 res = 1;
474 ast_verb(3, "Called %s\n", channel->device);
475 }
476
477 return res;
478}
int ast_call(struct ast_channel *chan, const char *addr, int timeout)
Make a call.
Definition channel.c:6456
#define AST_CHANNEL_NAME
Definition channel.h:173
void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer, const char *dialstring, const char *dialstatus)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
#define ast_verb(level,...)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.

References ast_call(), ast_channel_lock, AST_CHANNEL_NAME, ast_channel_name(), ast_channel_publish_dial(), ast_channel_unlock, ast_copy_string(), ast_hangup(), ast_verb, begin_dial_prerun(), ast_dial_channel::device, NULL, ast_dial_channel::owner, and pbx_builtin_setvar_helper().

Referenced by begin_dial(), and handle_call_forward().

◆ begin_dial_prerun()

static int begin_dial_prerun ( struct ast_dial_channel channel,
struct ast_channel chan,
struct ast_format_cap cap,
const char *  predial_string 
)
static

Helper function that requests all channels.

Definition at line 330 of file dial.c.

331{
332 struct ast_format_cap *cap_all_audio = NULL;
333 struct ast_format_cap *cap_request;
334 struct ast_format_cap *requester_cap = NULL;
335 struct ast_assigned_ids assignedids = {
336 .uniqueid = channel->assignedid1,
337 .uniqueid2 = channel->assignedid2,
338 };
339
340 if (chan) {
341 int max_forwards;
342
343 ast_channel_lock(chan);
345 requester_cap = ao2_bump(ast_channel_nativeformats(chan));
346 ast_channel_unlock(chan);
347
348 if (max_forwards <= 0) {
349 ast_log(LOG_WARNING, "Cannot dial from channel '%s'. Max forwards exceeded\n",
350 ast_channel_name(chan));
351 }
352 }
353
354 if (!channel->owner) {
355 if (cap && ast_format_cap_count(cap)) {
356 cap_request = cap;
357 } else if (requester_cap) {
358 cap_request = requester_cap;
359 } else {
362 cap_request = cap_all_audio;
363 }
364
365 /* If we fail to create our owner channel bail out */
366 if (!(channel->owner = ast_request(channel->tech, cap_request, &assignedids, chan, channel->device, &channel->cause))) {
367 ao2_cleanup(cap_all_audio);
368 return -1;
369 }
370 cap_request = NULL;
371 ao2_cleanup(requester_cap);
372 ao2_cleanup(cap_all_audio);
373 }
374
375 if (chan) {
376 ast_channel_lock_both(chan, channel->owner);
377 } else {
378 ast_channel_lock(channel->owner);
379 }
380
382
383 ast_channel_appl_set(channel->owner, "AppDial2");
384 ast_channel_data_set(channel->owner, "(Outgoing Line)");
385
386 memset(ast_channel_whentohangup(channel->owner), 0, sizeof(*ast_channel_whentohangup(channel->owner)));
387
388 /* Inherit everything from he who spawned this dial */
389 if (chan) {
390 ast_channel_inherit_variables(chan, channel->owner);
391 ast_channel_datastore_inherit(chan, channel->owner);
393
394 /* Copy over callerid information */
396
398
400
401 ast_channel_language_set(channel->owner, ast_channel_language(chan));
404 } else {
406 }
408 ast_channel_musicclass_set(channel->owner, ast_channel_musicclass(chan));
409
412 ast_channel_unlock(chan);
413 }
414
416 ast_channel_unlock(channel->owner);
417
418 if (!ast_strlen_zero(predial_string)) {
419 if (chan) {
421 }
422 ast_pre_call(channel->owner, predial_string);
423 if (chan) {
425 }
426 }
427
428 return 0;
429}
#define ast_log
Definition astobj2.c:42
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition astobj2.h:480
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
void ast_channel_appl_set(struct ast_channel *chan, const char *value)
@ AST_CHANNEL_REQUESTOR_BRIDGE_PEER
Definition channel.h:1525
@ AST_CHANNEL_REQUESTOR_REPLACEMENT
Definition channel.h:1527
const char * ast_channel_musicclass(const struct ast_channel *chan)
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
void ast_channel_data_set(struct ast_channel *chan, const char *value)
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
unsigned short ast_channel_transfercapability(const struct ast_channel *chan)
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition channel.h:2989
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition channel.c:2358
void ast_channel_req_accountcodes(struct ast_channel *chan, const struct ast_channel *requestor, enum ast_channel_requestor_relationship relationship)
Setup new channel accountcodes from the requestor channel after ast_request().
Definition channel.c:6429
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
ast_channel_adsicpe
Definition channel.h:888
void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
Inherits channel variable from parent to child channel.
Definition channel.c:6771
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
struct timeval * ast_channel_whentohangup(struct ast_channel *chan)
const char * ast_channel_language(const struct ast_channel *chan)
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
Definition channel.c:8337
int ast_pre_call(struct ast_channel *chan, const char *sub_args)
Execute a Gosub call on the channel before a call is placed.
Definition channel.c:6439
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_transfercapability_set(struct ast_channel *chan, unsigned short value)
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
struct ast_channel * ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
Requests a channel.
Definition channel.c:6349
void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
Copy the source redirecting information to the destination redirecting.
Definition channel.c:2121
@ AST_MEDIA_TYPE_AUDIO
Definition codec.h:32
@ AST_DIAL_OPTION_DIAL_REPLACES_SELF
Definition dial.h:48
int ast_format_cap_append_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Add all codecs Asterisk knows about for a specific type to the capabilities structure.
Definition format_cap.c:216
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition format_cap.h:38
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition format_cap.h:49
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition format_cap.c:395
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
#define LOG_WARNING
int ast_max_forwards_decrement(struct ast_channel *chan)
Decrement the max forwards count for a particular channel.
int ast_max_forwards_get(struct ast_channel *chan)
Get the current max forwards for a particular channel.
Structure to pass both assignedid values to channel drivers.
Definition channel.h:606
const char * uniqueid
Definition channel.h:607
Format capabilities structure, holds formats + preference order + etc.
Definition format_cap.c:54
int transit_network_select
Transit Network Select.
Definition channel.h:399
Channel datastore data for max forwards.

References ao2_bump, ao2_cleanup, ast_dial_channel::assignedid1, ast_dial_channel::assignedid2, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_adsicpe_set(), ast_channel_appl_set(), ast_channel_caller(), ast_channel_connected(), ast_channel_data_set(), ast_channel_datastore_inherit(), ast_channel_dialed(), ast_channel_inherit_variables(), ast_channel_language(), ast_channel_lock, ast_channel_lock_both, ast_channel_musicclass(), ast_channel_name(), ast_channel_nativeformats(), ast_channel_redirecting(), ast_channel_req_accountcodes(), AST_CHANNEL_REQUESTOR_BRIDGE_PEER, AST_CHANNEL_REQUESTOR_REPLACEMENT, ast_channel_stage_snapshot(), ast_channel_stage_snapshot_done(), ast_channel_transfercapability(), ast_channel_transfercapability_set(), ast_channel_unlock, ast_channel_whentohangup(), ast_connected_line_copy_from_caller(), AST_DIAL_OPTION_DIAL_REPLACES_SELF, ast_format_cap_alloc, ast_format_cap_append_by_type(), ast_format_cap_count(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_log, ast_max_forwards_decrement(), ast_max_forwards_get(), AST_MEDIA_TYPE_AUDIO, ast_party_redirecting_copy(), ast_pre_call(), ast_request(), ast_strlen_zero(), ast_dial_channel::cause, ast_dial_channel::device, LOG_WARNING, NULL, ast_dial_channel::options, ast_dial_channel::owner, ast_dial_channel::tech, ast_party_dialed::transit_network_select, and ast_assigned_ids::uniqueid.

Referenced by ast_dial_prerun(), and begin_dial_channel().

◆ dial_append_common()

static int dial_append_common ( struct ast_dial dial,
struct ast_dial_channel channel,
const char *  tech,
const char *  device,
const struct ast_assigned_ids assignedids 
)
static

Definition at line 247 of file dial.c.

249{
250 /* Record technology and device for when we actually dial */
251 channel->tech = ast_strdup(tech);
252 channel->device = ast_strdup(device);
253
254 /* Store the assigned id */
255 if (assignedids && !ast_strlen_zero(assignedids->uniqueid)) {
256 channel->assignedid1 = ast_strdup(assignedids->uniqueid);
257
258 if (!ast_strlen_zero(assignedids->uniqueid2)) {
259 channel->assignedid2 = ast_strdup(assignedids->uniqueid2);
260 }
261 }
262
263 /* Grab reference number from dial structure */
264 channel->num = ast_atomic_fetchadd_int(&dial->num, +1);
265
266 /* No timeout exists... yet */
267 channel->timeout = -1;
268
269 /* Insert into channels list */
270 AST_LIST_INSERT_TAIL(&dial->channels, channel, list);
271
272 return channel->num;
273
274}
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition lock.h:764
const char * uniqueid2
Definition channel.h:608
int num
Definition dial.c:49

References ast_dial_channel::assignedid1, ast_dial_channel::assignedid2, ast_atomic_fetchadd_int(), AST_LIST_INSERT_TAIL, ast_strdup, ast_strlen_zero(), ast_dial::channels, ast_dial_channel::device, ast_dial::num, ast_dial_channel::num, ast_dial_channel::tech, ast_dial_channel::timeout, ast_assigned_ids::uniqueid, and ast_assigned_ids::uniqueid2.

Referenced by ast_dial_append(), and ast_dial_append_channel().

◆ find_dial_channel()

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 1165 of file dial.c.

1166{
1167 struct ast_dial_channel *channel = AST_LIST_LAST(&dial->channels);
1168
1169 /* We can try to predict programmer behavior, the last channel they added is probably the one they wanted to modify */
1170 if (channel->num == num)
1171 return channel;
1172
1173 /* Hrm not at the end... looking through the list it is! */
1174 AST_LIST_LOCK(&dial->channels);
1175 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
1176 if (channel->num == num)
1177 break;
1178 }
1179 AST_LIST_UNLOCK(&dial->channels);
1180
1181 return channel;
1182}
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.

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_get_channel(), ast_dial_option_disable(), ast_dial_option_enable(), ast_dial_reason(), and ast_dial_set_timeout().

◆ find_relative_dial_channel()

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 557 of file dial.c.

558{
559 struct ast_dial_channel *channel = NULL;
560
561 AST_LIST_LOCK(&dial->channels);
562 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
563 if (channel->owner == owner)
564 break;
565 }
567
568 return channel;
569}

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_dial::channels, ast_dial_channel::list, NULL, and ast_dial_channel::owner.

Referenced by monitor_dial().

◆ handle_call_forward()

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 499 of file dial.c.

500{
501 struct ast_channel *original = channel->owner;
502 char *tmp = ast_strdupa(ast_channel_call_forward(channel->owner));
503 char *tech = "Local", *device = tmp, *stuff;
504 char *predial_string = dial->options[AST_DIAL_OPTION_PREDIAL];
505
506 /* If call forwarding is disabled just drop the original channel and don't attempt to dial the new one */
508 ast_hangup(original);
509 channel->owner = NULL;
510 return 0;
511 }
512
513 /* Figure out the new destination */
514 if ((stuff = strchr(tmp, '/'))) {
515 *stuff++ = '\0';
516 tech = tmp;
517 device = stuff;
518 } else {
519 const char *forward_context;
520 char destination[AST_MAX_CONTEXT + AST_MAX_EXTENSION + 1];
521
522 ast_channel_lock(original);
523 forward_context = pbx_builtin_getvar_helper(original, "FORWARD_CONTEXT");
524 snprintf(destination, sizeof(destination), "%s@%s", tmp, S_OR(forward_context, ast_channel_context(original)));
525 ast_channel_unlock(original);
526 device = ast_strdupa(destination);
527 }
528
529 /* Drop old destination information */
530 ast_free(channel->tech);
531 ast_free(channel->device);
532 ast_free(channel->assignedid1);
533 channel->assignedid1 = NULL;
534 ast_free(channel->assignedid2);
535 channel->assignedid2 = NULL;
536
537 /* Update the dial channel with the new destination information */
538 channel->tech = ast_strdup(tech);
539 channel->device = ast_strdup(device);
541
542 /* Drop the original channel */
543 channel->owner = NULL;
544
545 /* Finally give it a go... send it out into the world */
546 begin_dial_channel(channel, chan, chan ? 0 : 1, predial_string, original);
547
548 ast_channel_publish_dial_forward(chan, original, channel->owner, NULL, "CANCEL",
549 ast_channel_call_forward(original));
550
551 ast_hangup(original);
552
553 return 0;
554}
const char * ast_channel_context(const struct ast_channel *chan)
#define AST_MAX_CONTEXT
Definition channel.h:135
const char * ast_channel_call_forward(const struct ast_channel *chan)
#define AST_MAX_EXTENSION
Definition channel.h:134
#define FIND_RELATIVE_OPTION(dial, dial_channel, ast_dial_option)
Macro for finding the option structure to use on a dialed channel.
Definition dial.c:214
@ AST_DIAL_OPTION_DISABLE_CALL_FORWARDING
Definition dial.h:46
void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_channel *peer, struct ast_channel *forwarded, const char *dialstring, const char *dialstatus, const char *forward)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition strings.h:80
const struct ast_channel_tech * tech

References ast_dial_channel::assignedid1, ast_dial_channel::assignedid2, ast_channel_call_forward(), ast_channel_context(), ast_channel_lock, ast_channel_publish_dial_forward(), ast_channel_unlock, AST_DIAL_OPTION_DISABLE_CALL_FORWARDING, AST_DIAL_OPTION_PREDIAL, ast_free, ast_hangup(), AST_LIST_UNLOCK, AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_strdup, ast_strdupa, begin_dial_channel(), ast_dial::channels, ast_dial_channel::device, FIND_RELATIVE_OPTION, NULL, ast_dial::options, ast_dial_channel::owner, pbx_builtin_getvar_helper(), S_OR, ast_channel::tech, and ast_dial_channel::tech.

Referenced by monitor_dial().

◆ handle_frame()

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 frames.

Definition at line 580 of file dial.c.

581{
582 if (fr->frametype == AST_FRAME_CONTROL) {
583 switch (fr->subclass.integer) {
585 if (chan) {
586 ast_verb(3, "%s answered %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
587 } else {
588 ast_verb(3, "%s answered\n", ast_channel_name(channel->owner));
589 }
590 AST_LIST_LOCK(&dial->channels);
591 AST_LIST_REMOVE(&dial->channels, channel, list);
592 AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
594 ast_channel_publish_dial(chan, channel->owner, channel->device, "ANSWER");
596 break;
597 case AST_CONTROL_BUSY:
598 ast_verb(3, "%s is busy\n", ast_channel_name(channel->owner));
599 ast_channel_publish_dial(chan, channel->owner, channel->device, "BUSY");
600 ast_hangup(channel->owner);
601 channel->cause = AST_CAUSE_USER_BUSY;
602 channel->owner = NULL;
603 break;
605 ast_verb(3, "%s is circuit-busy\n", ast_channel_name(channel->owner));
606 ast_channel_publish_dial(chan, channel->owner, channel->device, "CONGESTION");
607 ast_hangup(channel->owner);
609 channel->owner = NULL;
610 break;
612 ast_verb(3, "%s dialed Incomplete extension %s\n", ast_channel_name(channel->owner), ast_channel_exten(channel->owner));
613 if (chan) {
615 } else {
616 ast_hangup(channel->owner);
617 channel->cause = AST_CAUSE_UNALLOCATED;
618 channel->owner = NULL;
619 }
620 break;
622 ast_verb(3, "%s is ringing\n", ast_channel_name(channel->owner));
623 ast_channel_publish_dial(chan, channel->owner, channel->device, "RINGING");
624 if (chan && !dial->options[AST_DIAL_OPTION_MUSIC])
627 break;
629 ast_channel_publish_dial(chan, channel->owner, channel->device, "PROGRESS");
630 if (chan) {
631 ast_verb(3, "%s is making progress, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
633 } else {
634 ast_verb(3, "%s is making progress\n", ast_channel_name(channel->owner));
635 }
637 break;
639 if (!chan) {
640 break;
641 }
642 ast_verb(3, "%s requested a video update, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
644 break;
646 if (!chan) {
647 break;
648 }
649 ast_verb(3, "%s requested a source update, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
651 break;
653 if (!chan) {
654 break;
655 }
656 ast_verb(3, "%s connected line has changed, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
657 if (ast_channel_connected_line_sub(channel->owner, chan, fr, 1)) {
659 }
660 break;
662 if (!chan) {
663 break;
664 }
665 ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
666 if (ast_channel_redirecting_sub(channel->owner, chan, fr, 1)) {
668 }
669 break;
671 ast_channel_publish_dial(chan, channel->owner, channel->device, "PROCEEDING");
672 if (chan) {
673 ast_verb(3, "%s is proceeding, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
675 } else {
676 ast_verb(3, "%s is proceeding\n", ast_channel_name(channel->owner));
677 }
679 break;
680 case AST_CONTROL_HOLD:
681 if (!chan) {
682 break;
683 }
684 ast_verb(3, "Call on %s placed on hold\n", ast_channel_name(chan));
686 break;
688 if (!chan) {
689 break;
690 }
691 ast_verb(3, "Call on %s left from hold\n", ast_channel_name(chan));
693 break;
696 break;
698 if (chan) {
700 }
701 break;
702 case -1:
703 if (chan) {
704 /* Prod the channel */
705 ast_indicate(chan, -1);
706 }
707 break;
708 default:
709 break;
710 }
711 }
712}
#define AST_CAUSE_UNALLOCATED
Definition causes.h:98
#define AST_CAUSE_NORMAL_CIRCUIT_CONGESTION
Definition causes.h:120
#define AST_CAUSE_USER_BUSY
Definition causes.h:107
int ast_channel_connected_line_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *connected_info, int frame)
Run a connected line interception subroutine and update a channel's connected line information.
Definition channel.c:10382
int ast_channel_redirecting_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *redirecting_info, int is_frame)
Run a redirecting interception subroutine and update a channel's redirecting information.
Definition channel.c:10427
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition channel.c:4648
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition channel.c:4270
const char * ast_channel_exten(const struct ast_channel *chan)
static void set_state(struct ast_dial *dial, enum ast_dial_result state)
Definition dial.c:571
@ AST_DIAL_RESULT_PROGRESS
Definition dial.h:59
@ AST_DIAL_RESULT_RINGING
Definition dial.h:58
@ AST_DIAL_RESULT_PROCEEDING
Definition dial.h:60
@ AST_DIAL_OPTION_MUSIC
Definition dial.h:45
@ AST_FRAME_CONTROL
@ AST_CONTROL_SRCUPDATE
@ AST_CONTROL_PROGRESS
@ AST_CONTROL_OFFHOOK
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_VIDUPDATE
@ AST_CONTROL_PROCEEDING
@ AST_CONTROL_REDIRECTING
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_ANSWER
@ AST_CONTROL_RINGING
@ AST_CONTROL_CONNECTED_LINE
@ AST_CONTROL_FLASH
@ AST_CONTROL_INCOMPLETE
@ AST_CONTROL_PVT_CAUSE_CODE
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
union ast_frame::@239 data

References AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, ast_channel_connected_line_sub(), ast_channel_exten(), ast_channel_name(), ast_channel_publish_dial(), ast_channel_redirecting_sub(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_OFFHOOK, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_PVT_CAUSE_CODE, AST_CONTROL_REDIRECTING, 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_indicate_data(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_verb, ast_dial_channel::cause, ast_dial::channels, ast_frame::data, ast_frame::datalen, ast_dial_channel::device, ast_frame::frametype, ast_frame_subclass::integer, ast_dial_channel::list, NULL, ast_dial::options, ast_dial_channel::owner, ast_frame::ptr, set_state(), and ast_frame::subclass.

Referenced by monitor_dial().

◆ handle_timeout_trip()

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 715 of file dial.c.

716{
717 struct ast_dial_channel *channel = NULL;
718 int diff = ast_tvdiff_ms(ast_tvnow(), start), lowest_timeout = -1, new_timeout = -1;
719
720 /* If there is no difference yet return the dial timeout so we can go again, we were likely interrupted */
721 if (!diff) {
722 return dial->timeout;
723 }
724
725 /* If the global dial timeout tripped switch the state to timeout so our channel loop will drop every channel */
726 if (diff >= dial->timeout) {
728 new_timeout = 0;
729 }
730
731 /* Go through dropping out channels that have met their timeout */
732 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
733 if (dial->state == AST_DIAL_RESULT_TIMEOUT || diff >= channel->timeout) {
734 ast_channel_lock(channel->owner);
736 ast_channel_unlock(channel->owner);
737 ast_hangup(channel->owner);
738 channel->cause = AST_CAUSE_NO_ANSWER;
739 channel->owner = NULL;
740 } else if ((lowest_timeout == -1) || (lowest_timeout > channel->timeout)) {
741 lowest_timeout = channel->timeout;
742 }
743 }
744
745 /* Calculate the new timeout using the lowest timeout found */
746 if (lowest_timeout >= 0)
747 new_timeout = lowest_timeout - diff;
748
749 return new_timeout;
750}
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
@ AST_DIAL_RESULT_TIMEOUT
Definition dial.h:62
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition time.h:159

References AST_CAUSE_NO_ANSWER, ast_channel_hangupcause_set(), ast_channel_lock, ast_channel_unlock, AST_DIAL_RESULT_TIMEOUT, ast_hangup(), AST_LIST_TRAVERSE, ast_tvdiff_ms(), ast_tvnow(), ast_dial_channel::cause, ast_dial::channels, ast_dial_channel::list, NULL, ast_dial_channel::owner, set_state(), ast_dial::state, ast_dial::timeout, and ast_dial_channel::timeout.

Referenced by monitor_dial().

◆ monitor_dial()

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 769 of file dial.c.

770{
771 int timeout = -1;
772 struct ast_channel *cs[AST_MAX_WATCHERS], *who = NULL;
773 struct ast_dial_channel *channel = NULL;
774 struct answer_exec_struct *answer_exec = NULL;
775 struct timeval start;
776
778
779 /* If the "always indicate ringing" option is set, change state to ringing and indicate to the owner if present */
780 if (dial->options[AST_DIAL_OPTION_RINGING]) {
782 if (chan)
784 } else if (chan && dial->options[AST_DIAL_OPTION_MUSIC] &&
786 char *original_moh = ast_strdupa(ast_channel_musicclass(chan));
787 ast_indicate(chan, -1);
788 ast_channel_musicclass_set(chan, dial->options[AST_DIAL_OPTION_MUSIC]);
790 ast_channel_musicclass_set(chan, original_moh);
791 }
792
793 /* Record start time for timeout purposes */
794 start = ast_tvnow();
795
796 /* We actually figured out the maximum timeout we can do as they were added, so we can directly access the info */
797 timeout = dial->actual_timeout;
798
799 /* Go into an infinite loop while we are trying */
801 int pos = 0, count = 0;
802 struct ast_frame *fr = NULL;
803
804 /* Set up channel structure array */
805 pos = count = 0;
806 if (chan)
807 cs[pos++] = chan;
808
809 /* Add channels we are attempting to dial */
810 AST_LIST_LOCK(&dial->channels);
811 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
812 if (channel->owner) {
813 cs[pos++] = channel->owner;
814 count++;
815 }
816 }
818
819 /* If we have no outbound channels in progress, switch state to unanswered and stop */
820 if (!count) {
822 break;
823 }
824
825 /* Just to be safe... */
826 if (dial->thread == AST_PTHREADT_STOP)
827 break;
828
829 /* Wait for frames from channels */
830 who = ast_waitfor_n(cs, pos, &timeout);
831
832 /* Check to see if our thread is being canceled */
833 if (dial->thread == AST_PTHREADT_STOP)
834 break;
835
836 /* If the timeout no longer exists OR if we got no channel it basically means the timeout was tripped, so handle it */
837 if (!timeout || !who) {
838 timeout = handle_timeout_trip(dial, start);
839 continue;
840 }
841
842 /* Find relative dial channel */
843 if (!chan || !IS_CALLER(chan, who))
844 channel = find_relative_dial_channel(dial, who);
845
846 /* See if this channel has been forwarded elsewhere */
848 handle_call_forward(dial, channel, chan);
849 continue;
850 }
851
852 /* Attempt to read in a frame */
853 if (!(fr = ast_read(who))) {
854 /* If this is the caller then we switch state to hangup and stop */
855 if (chan && IS_CALLER(chan, who)) {
857 break;
858 }
860 ast_hangup(who);
861 channel->owner = NULL;
862 continue;
863 }
864
865 /* Process the frame */
866 handle_frame(dial, channel, fr, chan);
867
868 /* Free the received frame and start all over */
869 ast_frfree(fr);
870 }
871
872 /* Do post-processing from loop */
873 if (dial->state == AST_DIAL_RESULT_ANSWERED) {
874 /* Hangup everything except that which answered */
875 AST_LIST_LOCK(&dial->channels);
876 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
877 if (!channel->owner || channel->owner == who)
878 continue;
879 ast_channel_publish_dial(chan, channel->owner, channel->device, "CANCEL");
880 ast_hangup(channel->owner);
882 channel->owner = NULL;
883 }
885 /* If ANSWER_EXEC is enabled as an option, execute application on answered channel */
886 if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC))) {
887 channel->is_running_app = 1;
888 answer_exec_run(dial, channel, answer_exec->app, answer_exec->args);
889 channel->is_running_app = 0;
890 }
891
892 if (chan && dial->options[AST_DIAL_OPTION_MUSIC] &&
894 ast_moh_stop(chan);
895 }
896 } else if (dial->state == AST_DIAL_RESULT_HANGUP) {
897 /* Hangup everything */
898 AST_LIST_LOCK(&dial->channels);
899 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
900 if (!channel->owner)
901 continue;
902 ast_channel_publish_dial(chan, channel->owner, channel->device, "CANCEL");
903 ast_hangup(channel->owner);
905 channel->owner = NULL;
906 }
908 }
909
911 enum ast_dial_result state = dial->state;
912
913 ast_dial_destroy(dial);
914 return state;
915 }
916
917 return dial->state;
918}
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition causes.h:114
#define AST_CAUSE_NORMAL_CLEARING
Definition causes.h:106
struct ast_channel * ast_waitfor_n(struct ast_channel **chan, int n, int *ms)
Waits for input on a group of channels Wait for input on an array of channels for a given # of millis...
Definition channel.c:3154
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition channel.c:4250
int ast_channel_hangupcause(const struct ast_channel *chan)
#define IS_CALLER(chan, owner)
Macro that determines whether a channel is the caller or not.
Definition dial.c:217
const char * ast_hangup_cause_to_dial_status(int hangup_cause)
Convert a hangup cause to a publishable dial status.
Definition dial.c:752
#define AST_MAX_WATCHERS
Maximum number of channels we can watch at a time.
Definition dial.c:211
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.
Definition dial.c:499
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.
Definition dial.c:557
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.
Definition dial.c:166
static int handle_timeout_trip(struct ast_dial *dial, struct timeval start)
Helper function to handle when a timeout occurs on dialing attempt.
Definition dial.c:715
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition dial.c:1094
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 frames.
Definition dial.c:580
@ AST_DIAL_RESULT_HANGUP
Definition dial.h:63
@ AST_DIAL_RESULT_UNANSWERED
Definition dial.h:64
@ AST_DIAL_OPTION_ANSWER_EXEC
Definition dial.h:44
@ AST_DIAL_OPTION_RINGING
Definition dial.h:43
@ AST_DIAL_OPTION_SELF_DESTROY
Definition dial.h:49
#define ast_frfree(fr)
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition channel.c:7778
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition channel.c:7788
unsigned int is_running_app
Definition dial.c:70
Data structure associated with a single frame of data.

References ast_dial::actual_timeout, answer_exec_run(), answer_exec_struct::app, answer_exec_struct::args, AST_CAUSE_ANSWERED_ELSEWHERE, AST_CAUSE_NORMAL_CLEARING, ast_channel_call_forward(), ast_channel_hangupcause(), ast_channel_musicclass(), ast_channel_publish_dial(), AST_CONTROL_RINGING, ast_dial_destroy(), AST_DIAL_OPTION_ANSWER_EXEC, AST_DIAL_OPTION_MUSIC, AST_DIAL_OPTION_RINGING, AST_DIAL_OPTION_SELF_DESTROY, 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_hangup_cause_to_dial_status(), ast_indicate(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MAX_WATCHERS, ast_moh_start(), ast_moh_stop(), AST_PTHREADT_STOP, ast_read(), ast_strdupa, ast_strlen_zero(), ast_tvnow(), ast_waitfor_n(), ast_dial_channel::cause, ast_dial::channels, ast_dial_channel::device, find_relative_dial_channel(), FIND_RELATIVE_OPTION, handle_call_forward(), handle_frame(), handle_timeout_trip(), IS_CALLER, ast_dial_channel::is_running_app, NULL, ast_dial::options, ast_dial_channel::owner, set_state(), ast_dial::state, ast_dial::thread, and ast_dial_channel::timeout.

Referenced by ast_dial_run(), and async_dial().

◆ music_disable()

static int music_disable ( void *  data)
static

Definition at line 139 of file dial.c.

140{
141 if (!data)
142 return -1;
143
144 ast_free(data);
145
146 return 0;
147}

References ast_free.

◆ music_enable()

static void * music_enable ( void *  data)
static

Definition at line 134 of file dial.c.

135{
136 return ast_strdup(data);
137}

References ast_strdup.

◆ predial_disable()

static int predial_disable ( void *  data)
static

Definition at line 154 of file dial.c.

155{
156 if (!data) {
157 return -1;
158 }
159
160 ast_free(data);
161
162 return 0;
163}

References ast_free.

◆ predial_enable()

static void * predial_enable ( void *  data)
static

Definition at line 149 of file dial.c.

150{
151 return ast_strdup(data);
152}

References ast_strdup.

◆ set_state()

static void set_state ( struct ast_dial dial,
enum ast_dial_result  state 
)
static

Definition at line 571 of file dial.c.

572{
573 dial->state = state;
574
575 if (dial->state_callback)
576 dial->state_callback(dial);
577}

References ast_dial::state, and ast_dial::state_callback.

Referenced by handle_frame(), handle_timeout_trip(), and monitor_dial().

Variable Documentation

◆ option_types

const struct ast_option_types option_types[]
static

Map options to respective handlers (enable/disable).

Note
This list MUST be perfectly kept in order with enum ast_dial_option, or else madness will happen.

Definition at line 199 of file dial.c.

199 {
200 { AST_DIAL_OPTION_RINGING, NULL, NULL }, /*!< Always indicate ringing to caller */
201 { AST_DIAL_OPTION_ANSWER_EXEC, answer_exec_enable, answer_exec_disable }, /*!< Execute application upon answer in async mode */
202 { AST_DIAL_OPTION_MUSIC, music_enable, music_disable }, /*!< Play music to the caller instead of ringing */
203 { AST_DIAL_OPTION_DISABLE_CALL_FORWARDING, NULL, NULL }, /*!< Disable call forwarding on channels */
204 { AST_DIAL_OPTION_PREDIAL, predial_enable, predial_disable }, /*!< Execute a subroutine on the outbound channels prior to dialing */
205 { AST_DIAL_OPTION_DIAL_REPLACES_SELF, NULL, NULL }, /*!< The dial operation is a replacement for the requester */
206 { AST_DIAL_OPTION_SELF_DESTROY, NULL, NULL}, /*!< Destroy self at end of ast_dial_run */
207 { AST_DIAL_OPTION_MAX, NULL, NULL }, /*!< Terminator of list */
208};
static int answer_exec_disable(void *data)
Disable function for 'ANSWER_EXEC' option.
Definition dial.c:116
static int predial_disable(void *data)
Definition dial.c:154
static void * answer_exec_enable(void *data)
Enable function for 'ANSWER_EXEC' option.
Definition dial.c:90
static void * predial_enable(void *data)
Definition dial.c:149
static void * music_enable(void *data)
Definition dial.c:134
static int music_disable(void *data)
Definition dial.c:139

Referenced by ast_dial_destroy(), ast_dial_option_disable(), ast_dial_option_enable(), ast_dial_option_global_disable(), and ast_dial_option_global_enable().