Asterisk - The Open Source Telephony Project GIT-master-d5a0626
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. More...
 
#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. More...
 
#define IS_CALLER(chan, owner)   (chan == owner ? 1 : 0)
 Macro that determines whether a channel is the caller or not. More...
 

Typedefs

typedef int(* ast_dial_option_cb_disable) (void *data)
 Typedef for dial option disable. More...
 
typedef void *(* ast_dial_option_cb_enable) (void *data)
 Typedef for dial option enable. More...
 

Functions

static int answer_exec_disable (void *data)
 Disable function for 'ANSWER_EXEC' option. More...
 
static void * answer_exec_enable (void *data)
 Enable function for 'ANSWER_EXEC' option. More...
 
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. More...
 
struct ast_channelast_dial_answered (struct ast_dial *dial)
 Return channel that answered. More...
 
struct ast_channelast_dial_answered_steal (struct ast_dial *dial)
 Steal the channel that answered. More...
 
int ast_dial_append (struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
 Append a channel. More...
 
int ast_dial_append_channel (struct ast_dial *dial, struct ast_channel *chan)
 Append a channel using an actual channel object. More...
 
struct ast_dialast_dial_create (void)
 New dialing structure. More...
 
int ast_dial_destroy (struct ast_dial *dial)
 Destroys a dialing structure. More...
 
struct ast_channelast_dial_get_channel (struct ast_dial *dial, int num)
 Get the dialing channel, if prerun has been executed. More...
 
void * ast_dial_get_user_data (struct ast_dial *dial)
 Return the user data on a dial structure. More...
 
void ast_dial_hangup (struct ast_dial *dial)
 Hangup channels. More...
 
enum ast_dial_result ast_dial_join (struct ast_dial *dial)
 Cancel async thread. More...
 
int ast_dial_option_disable (struct ast_dial *dial, int num, enum ast_dial_option option)
 Disables an option per channel. More...
 
int ast_dial_option_enable (struct ast_dial *dial, int num, enum ast_dial_option option, void *data)
 Enables an option per channel. More...
 
int ast_dial_option_global_disable (struct ast_dial *dial, enum ast_dial_option option)
 Disables an option globally. More...
 
int ast_dial_option_global_enable (struct ast_dial *dial, enum ast_dial_option option, void *data)
 Enables an option globally. More...
 
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. More...
 
int ast_dial_reason (struct ast_dial *dial, int num)
 Get the reason an outgoing channel has failed. More...
 
enum ast_dial_result ast_dial_run (struct ast_dial *dial, struct ast_channel *chan, int async)
 Execute dialing synchronously or asynchronously. More...
 
void ast_dial_set_global_timeout (struct ast_dial *dial, int timeout)
 Set the maximum time (globally) allowed for trying to ring phones. More...
 
void ast_dial_set_state_callback (struct ast_dial *dial, ast_dial_state_callback callback)
 Set a callback for state changes. More...
 
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. More...
 
void ast_dial_set_user_data (struct ast_dial *dial, void *user_data)
 Set user data on a dial structure. More...
 
enum ast_dial_result ast_dial_state (struct ast_dial *dial)
 Return state of dial. More...
 
const char * ast_hangup_cause_to_dial_status (int hangup_cause)
 Convert a hangup cause to a publishable dial status. More...
 
static void * async_dial (void *data)
 Dial async thread function. More...
 
static int begin_dial (struct ast_dial *dial, struct ast_channel *chan, int async)
 Helper function that does the beginning dialing per dial structure. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
static int handle_timeout_trip (struct ast_dial *dial, struct timeval start)
 Helper function to handle when a timeout occurs on dialing attempt. More...
 
static enum ast_dial_result monitor_dial (struct ast_dial *dial, struct ast_channel *chan)
 Helper function that basically keeps tabs on dialing attempts. More...
 
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). More...
 

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[]
Definition: app_adsiprog.c:56
#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
#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
const char * args

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:2560
#define AST_PTHREADT_STOP
Definition: lock.h:67
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
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 977 of file dial.c.

978{
979 if (!dial)
980 return NULL;
981
982 return ((dial->state == AST_DIAL_RESULT_ANSWERED) ? AST_LIST_FIRST(&dial->channels)->owner : NULL);
983}
@ AST_DIAL_RESULT_ANSWERED
Definition: dial.h:61
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
enum ast_dial_result state
Definition: dial.c:52
struct ast_dial::@343 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 989 of file dial.c.

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

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.
Definition: linkedlists.h:626
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ast_mutex_init(pmutex)
Definition: lock.h:186
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 1091 of file dial.c.

1092{
1093 int i = 0;
1094 struct ast_dial_channel *channel = NULL;
1095
1096 if (!dial)
1097 return -1;
1098
1099 /* Hangup and deallocate all the dialed channels */
1100 AST_LIST_LOCK(&dial->channels);
1101 AST_LIST_TRAVERSE_SAFE_BEGIN(&dial->channels, channel, list) {
1102 /* Disable any enabled options */
1103 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
1104 if (!channel->options[i])
1105 continue;
1106 if (option_types[i].disable)
1107 option_types[i].disable(channel->options[i]);
1108 channel->options[i] = NULL;
1109 }
1110
1111 /* Hang up channel if need be */
1112 ast_hangup(channel->owner);
1113 channel->owner = NULL;
1114
1115 /* Free structure */
1116 ast_free(channel->tech);
1117 ast_free(channel->device);
1118 ast_free(channel->assignedid1);
1119 ast_free(channel->assignedid2);
1120
1122 ast_free(channel);
1123 }
1125 AST_LIST_UNLOCK(&dial->channels);
1126
1127 /* Disable any enabled options globally */
1128 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
1129 if (!dial->options[i])
1130 continue;
1131 if (option_types[i].disable)
1132 option_types[i].disable(dial->options[i]);
1133 dial->options[i] = NULL;
1134 }
1135
1136 /* Lock be gone! */
1137 ast_mutex_destroy(&dial->lock);
1138
1139 /* Free structure */
1140 ast_free(dial);
1141
1142 return 0;
1143}
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.
Definition: linkedlists.h:615
#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.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define ast_mutex_destroy(a)
Definition: lock.h:188
char * assignedid2
Definition: dial.c:72
void * options[AST_DIAL_OPTION_MAX]
Definition: dial.c:68
char * assignedid1
Definition: dial.c:71
struct ast_dial_channel::@344 list
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 1258 of file dial.c.

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

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

1280{
1281 return dial->user_data;
1282}
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 1074 of file dial.c.

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

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

1018{
1019 pthread_t thread;
1020
1021 /* If the dial structure is not running in async, return failed */
1022 if (dial->thread == AST_PTHREADT_NULL)
1024
1025 /* Record thread */
1026 thread = dial->thread;
1027
1028 /* Boom, commence locking */
1029 ast_mutex_lock(&dial->lock);
1030
1031 /* Stop the thread */
1032 dial->thread = AST_PTHREADT_STOP;
1033
1034 /* If the answered channel is running an application we have to soft hangup it, can't just poke the thread */
1035 AST_LIST_LOCK(&dial->channels);
1036 if (AST_LIST_FIRST(&dial->channels)->is_running_app) {
1037 struct ast_channel *chan = AST_LIST_FIRST(&dial->channels)->owner;
1038 if (chan) {
1039 ast_channel_lock(chan);
1041 ast_channel_unlock(chan);
1042 }
1043 } else {
1044 struct ast_dial_channel *channel = NULL;
1045
1046 /* Now we signal it with SIGURG so it will break out of it's waitfor */
1047 pthread_kill(thread, SIGURG);
1048
1049 /* 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. */
1050 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
1051 if (channel->owner) {
1053 }
1054 }
1055 }
1056 AST_LIST_UNLOCK(&dial->channels);
1057
1058 /* Yay done with it */
1059 ast_mutex_unlock(&dial->lock);
1060
1061 /* Finally wait for the thread to exit */
1062 pthread_join(thread, NULL);
1063
1064 /* Yay thread is all gone */
1065 dial->thread = AST_PTHREADT_NULL;
1066
1067 return dial->state;
1068}
pthread_t thread
Definition: app_sla.c:329
#define ast_channel_lock(chan)
Definition: channel.h:2968
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2490
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1168
#define ast_channel_unlock(chan)
Definition: channel.h:2969
@ 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 1222 of file dial.c.

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

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

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

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

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

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

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

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

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

936{
938
939 /* Ensure required arguments are passed */
940 if (!dial) {
941 ast_debug(1, "invalid #1\n");
943 }
944
945 /* If there are no channels to dial we can't very well try to dial them */
946 if (AST_LIST_EMPTY(&dial->channels)) {
947 ast_debug(1, "invalid #2\n");
949 }
950
951 /* Dial each requested channel */
952 if (!begin_dial(dial, chan, async))
954
955 /* If we are running async spawn a thread and send it away... otherwise block here */
956 if (async) {
957 /* reference be released at dial destruction if it isn't NULL */
960 /* Try to create a thread */
961 if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) {
962 /* Failed to create the thread - hangup all dialed channels and return failed */
963 ast_dial_hangup(dial);
965 }
966 } else {
967 res = monitor_dial(dial, chan);
968 }
969
970 return res;
971}
static void * async_dial(void *data)
Dial async thread function.
Definition: dial.c:918
void ast_dial_hangup(struct ast_dial *dial)
Hangup channels.
Definition: dial.c:1074
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:766
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 callerid from the thread
Definition: logger.c:2298
ast_callid callid
Definition: dial.c:58
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:584

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

1285{
1286 dial->timeout = timeout;
1287
1288 if (dial->timeout > 0 && (dial->actual_timeout > dial->timeout || dial->actual_timeout == -1))
1289 dial->actual_timeout = dial->timeout;
1290
1291 return;
1292}

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

1270{
1271 dial->state_callback = callback;
1272}
ast_dial_state_callback state_callback
Definition: dial.c:54

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

1295{
1296 struct ast_dial_channel *channel = NULL;
1297
1298 if (!(channel = find_dial_channel(dial, num)))
1299 return;
1300
1301 channel->timeout = timeout;
1302
1303 if (channel->timeout > 0 && (dial->actual_timeout > channel->timeout || dial->actual_timeout == -1))
1304 dial->actual_timeout = channel->timeout;
1305
1306 return;
1307}
int timeout
Definition: dial.c:65

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

1275{
1276 dial->user_data = user_data;
1277}

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

1009{
1010 return dial->state;
1011}

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

750{
751 switch(hangup_cause) {
752 case AST_CAUSE_BUSY:
753 return "BUSY";
755 return "CONGESTION";
758 return "CHANUNAVAIL";
760 default:
761 return "NOANSWER";
762 }
763}
#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 918 of file dial.c.

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

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:6480
#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...
Definition: autoservice.c:266
void ast_channel_appl_set(struct ast_channel *chan, const char *value)
@ AST_CHANNEL_REQUESTOR_BRIDGE_PEER
Definition: channel.h:1523
@ AST_CHANNEL_REQUESTOR_REPLACEMENT
Definition: channel.h:1525
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:2975
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:2387
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:6453
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
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:6790
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:8315
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:6463
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:6373
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:2154
@ 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.
Definition: max_forwards.c:135
int ast_max_forwards_get(struct ast_channel *chan)
Get the current max forwards for a particular channel.
Definition: max_forwards.c:121
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.
Definition: max_forwards.c:29

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.
Definition: linkedlists.h:731
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:757
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 1162 of file dial.c.

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

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;
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}
static int tmp()
Definition: bt_open.c:389
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, ast_dial_channel::tech, and tmp().

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:10360
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:10405
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:4672
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4296
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_BUSY
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_VIDUPDATE
@ AST_CONTROL_PROCEEDING
@ AST_CONTROL_REDIRECTING
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_ANSWER
@ AST_CONTROL_RINGING
@ AST_CONTROL_HOLD
@ 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.
Definition: linkedlists.h:711
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:856
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype

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_hangup(channel->owner);
735 channel->cause = AST_CAUSE_NO_ANSWER;
736 channel->owner = NULL;
737 } else if ((lowest_timeout == -1) || (lowest_timeout > channel->timeout)) {
738 lowest_timeout = channel->timeout;
739 }
740 }
741
742 /* Calculate the new timeout using the lowest timeout found */
743 if (lowest_timeout >= 0)
744 new_timeout = lowest_timeout - diff;
745
746 return new_timeout;
747}
@ 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_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 766 of file dial.c.

767{
768 int timeout = -1;
769 struct ast_channel *cs[AST_MAX_WATCHERS], *who = NULL;
770 struct ast_dial_channel *channel = NULL;
771 struct answer_exec_struct *answer_exec = NULL;
772 struct timeval start;
773
775
776 /* If the "always indicate ringing" option is set, change state to ringing and indicate to the owner if present */
777 if (dial->options[AST_DIAL_OPTION_RINGING]) {
779 if (chan)
781 } else if (chan && dial->options[AST_DIAL_OPTION_MUSIC] &&
783 char *original_moh = ast_strdupa(ast_channel_musicclass(chan));
784 ast_indicate(chan, -1);
785 ast_channel_musicclass_set(chan, dial->options[AST_DIAL_OPTION_MUSIC]);
787 ast_channel_musicclass_set(chan, original_moh);
788 }
789
790 /* Record start time for timeout purposes */
791 start = ast_tvnow();
792
793 /* We actually figured out the maximum timeout we can do as they were added, so we can directly access the info */
794 timeout = dial->actual_timeout;
795
796 /* Go into an infinite loop while we are trying */
798 int pos = 0, count = 0;
799 struct ast_frame *fr = NULL;
800
801 /* Set up channel structure array */
802 pos = count = 0;
803 if (chan)
804 cs[pos++] = chan;
805
806 /* Add channels we are attempting to dial */
807 AST_LIST_LOCK(&dial->channels);
808 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
809 if (channel->owner) {
810 cs[pos++] = channel->owner;
811 count++;
812 }
813 }
815
816 /* If we have no outbound channels in progress, switch state to unanswered and stop */
817 if (!count) {
819 break;
820 }
821
822 /* Just to be safe... */
823 if (dial->thread == AST_PTHREADT_STOP)
824 break;
825
826 /* Wait for frames from channels */
827 who = ast_waitfor_n(cs, pos, &timeout);
828
829 /* Check to see if our thread is being canceled */
830 if (dial->thread == AST_PTHREADT_STOP)
831 break;
832
833 /* If the timeout no longer exists OR if we got no channel it basically means the timeout was tripped, so handle it */
834 if (!timeout || !who) {
835 timeout = handle_timeout_trip(dial, start);
836 continue;
837 }
838
839 /* Find relative dial channel */
840 if (!chan || !IS_CALLER(chan, who))
841 channel = find_relative_dial_channel(dial, who);
842
843 /* See if this channel has been forwarded elsewhere */
845 handle_call_forward(dial, channel, chan);
846 continue;
847 }
848
849 /* Attempt to read in a frame */
850 if (!(fr = ast_read(who))) {
851 /* If this is the caller then we switch state to hangup and stop */
852 if (chan && IS_CALLER(chan, who)) {
854 break;
855 }
857 ast_hangup(who);
858 channel->owner = NULL;
859 continue;
860 }
861
862 /* Process the frame */
863 handle_frame(dial, channel, fr, chan);
864
865 /* Free the received frame and start all over */
866 ast_frfree(fr);
867 }
868
869 /* Do post-processing from loop */
870 if (dial->state == AST_DIAL_RESULT_ANSWERED) {
871 /* Hangup everything except that which answered */
872 AST_LIST_LOCK(&dial->channels);
873 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
874 if (!channel->owner || channel->owner == who)
875 continue;
876 ast_channel_publish_dial(chan, channel->owner, channel->device, "CANCEL");
877 ast_hangup(channel->owner);
879 channel->owner = NULL;
880 }
882 /* If ANSWER_EXEC is enabled as an option, execute application on answered channel */
883 if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC))) {
884 channel->is_running_app = 1;
885 answer_exec_run(dial, channel, answer_exec->app, answer_exec->args);
886 channel->is_running_app = 0;
887 }
888
889 if (chan && dial->options[AST_DIAL_OPTION_MUSIC] &&
891 ast_moh_stop(chan);
892 }
893 } else if (dial->state == AST_DIAL_RESULT_HANGUP) {
894 /* Hangup everything */
895 AST_LIST_LOCK(&dial->channels);
896 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
897 if (!channel->owner)
898 continue;
899 ast_channel_publish_dial(chan, channel->owner, channel->device, "CANCEL");
900 ast_hangup(channel->owner);
902 channel->owner = NULL;
903 }
905 }
906
908 enum ast_dial_result state = dial->state;
909
910 ast_dial_destroy(dial);
911 return state;
912 }
913
914 return dial->state;
915}
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition: causes.h:114
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:106
enum cc_state state
Definition: ccss.c:393
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:3176
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4276
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:749
#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:1091
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:7788
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7798
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(), 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 state, 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.

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