mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-25 07:01:09 +00:00
- Add the ability to register a callback to monitor state changes in an
asynchronous dial operation. - Rename the various references to "status" to "state" in the dial API git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@54066 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -3143,7 +3143,7 @@ static void *sla_thread(void *data)
|
|||||||
ast_mutex_t cond_lock;
|
ast_mutex_t cond_lock;
|
||||||
ast_cond_t cond;
|
ast_cond_t cond;
|
||||||
|
|
||||||
switch ((dial_res = ast_dial_status(station_ref->station->dial))) {
|
switch ((dial_res = ast_dial_state(station_ref->station->dial))) {
|
||||||
case AST_DIAL_RESULT_HANGUP:
|
case AST_DIAL_RESULT_HANGUP:
|
||||||
case AST_DIAL_RESULT_INVALID:
|
case AST_DIAL_RESULT_INVALID:
|
||||||
case AST_DIAL_RESULT_FAILED:
|
case AST_DIAL_RESULT_FAILED:
|
||||||
@@ -3286,7 +3286,7 @@ static void *dial_trunk(void *data)
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
unsigned int done = 0;
|
unsigned int done = 0;
|
||||||
switch ((dial_res = ast_dial_status(dial))) {
|
switch ((dial_res = ast_dial_state(dial))) {
|
||||||
case AST_DIAL_RESULT_ANSWERED:
|
case AST_DIAL_RESULT_ANSWERED:
|
||||||
trunk->chan = ast_dial_answered(dial);
|
trunk->chan = ast_dial_answered(dial);
|
||||||
case AST_DIAL_RESULT_HANGUP:
|
case AST_DIAL_RESULT_HANGUP:
|
||||||
|
@@ -168,7 +168,7 @@ static int page_exec(struct ast_channel *chan, void *data)
|
|||||||
struct ast_dial *dial = dials[i];
|
struct ast_dial *dial = dials[i];
|
||||||
|
|
||||||
/* If the dial is already answered, then they will/should get kicked out by Meetme */
|
/* If the dial is already answered, then they will/should get kicked out by Meetme */
|
||||||
if (ast_dial_status(dial) != AST_DIAL_RESULT_ANSWERED)
|
if (ast_dial_state(dial) != AST_DIAL_RESULT_ANSWERED)
|
||||||
ast_dial_join(dial);
|
ast_dial_join(dial);
|
||||||
|
|
||||||
/* Hangup all channels */
|
/* Hangup all channels */
|
||||||
|
@@ -33,6 +33,8 @@ struct ast_dial;
|
|||||||
/*! \brief Dialing channel structure. Contains per-channel dialing options, asterisk channel, and more! */
|
/*! \brief Dialing channel structure. Contains per-channel dialing options, asterisk channel, and more! */
|
||||||
struct ast_dial_channel;
|
struct ast_dial_channel;
|
||||||
|
|
||||||
|
typedef void (*ast_dial_state_callback)(struct ast_dial *);
|
||||||
|
|
||||||
/*! \brief List of options that are applicable either globally or per dialed channel */
|
/*! \brief List of options that are applicable either globally or per dialed channel */
|
||||||
enum ast_dial_option {
|
enum ast_dial_option {
|
||||||
AST_DIAL_OPTION_RINGING, /*!< Always indicate ringing to caller */
|
AST_DIAL_OPTION_RINGING, /*!< Always indicate ringing to caller */
|
||||||
@@ -78,11 +80,11 @@ enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *cha
|
|||||||
*/
|
*/
|
||||||
struct ast_channel *ast_dial_answered(struct ast_dial *dial);
|
struct ast_channel *ast_dial_answered(struct ast_dial *dial);
|
||||||
|
|
||||||
/*! \brief Return status of dial
|
/*! \brief Return state of dial
|
||||||
* \note Returns the status of the dial attempt
|
* \note Returns the state of the dial attempt
|
||||||
* \param dial Dialing structure
|
* \param dial Dialing structure
|
||||||
*/
|
*/
|
||||||
enum ast_dial_result ast_dial_status(struct ast_dial *dial);
|
enum ast_dial_result ast_dial_state(struct ast_dial *dial);
|
||||||
|
|
||||||
/*! \brief Cancel async thread
|
/*! \brief Cancel async thread
|
||||||
* \note Cancel a running async thread
|
* \note Cancel a running async thread
|
||||||
@@ -135,6 +137,13 @@ int ast_dial_option_global_disable(struct ast_dial *dial, enum ast_dial_option o
|
|||||||
*/
|
*/
|
||||||
int ast_dial_option_disable(struct ast_dial *dial, int num, enum ast_dial_option option);
|
int ast_dial_option_disable(struct ast_dial *dial, int num, enum ast_dial_option option);
|
||||||
|
|
||||||
|
/*! \brief Set a callback for state changes
|
||||||
|
* \param dial The dial structure to watch for state changes
|
||||||
|
* \param callback the callback
|
||||||
|
* \return nothing
|
||||||
|
*/
|
||||||
|
void ast_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback);
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
65
main/dial.c
65
main/dial.c
@@ -47,8 +47,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||||||
/*! \brief Main dialing structure. Contains global options, channels being dialed, and more! */
|
/*! \brief Main dialing structure. Contains global options, channels being dialed, and more! */
|
||||||
struct ast_dial {
|
struct ast_dial {
|
||||||
int num; /*! Current number to give to next dialed channel */
|
int num; /*! Current number to give to next dialed channel */
|
||||||
enum ast_dial_result status; /*! Status of dial */
|
enum ast_dial_result state; /*! Status of dial */
|
||||||
void *options[AST_DIAL_OPTION_MAX]; /*! Global options */
|
void *options[AST_DIAL_OPTION_MAX]; /*! Global options */
|
||||||
|
ast_dial_state_callback state_callback; /*! Status callback */
|
||||||
AST_LIST_HEAD_NOLOCK(, ast_dial_channel) channels; /*! Channels being dialed */
|
AST_LIST_HEAD_NOLOCK(, ast_dial_channel) channels; /*! Channels being dialed */
|
||||||
pthread_t thread; /*! Thread (if running in async) */
|
pthread_t thread; /*! Thread (if running in async) */
|
||||||
};
|
};
|
||||||
@@ -288,6 +289,14 @@ static struct ast_dial_channel *find_relative_dial_channel(struct ast_dial *dial
|
|||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_state(struct ast_dial *dial, enum ast_dial_result state)
|
||||||
|
{
|
||||||
|
dial->state = state;
|
||||||
|
|
||||||
|
if (dial->state_callback)
|
||||||
|
dial->state_callback(dial);
|
||||||
|
}
|
||||||
|
|
||||||
/*! \brief Helper function that handles control frames WITH owner */
|
/*! \brief Helper function that handles control frames WITH owner */
|
||||||
static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr, struct ast_channel *chan)
|
static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr, struct ast_channel *chan)
|
||||||
{
|
{
|
||||||
@@ -298,7 +307,7 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel
|
|||||||
ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", channel->owner->name, chan->name);
|
ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", channel->owner->name, chan->name);
|
||||||
AST_LIST_REMOVE(&dial->channels, channel, list);
|
AST_LIST_REMOVE(&dial->channels, channel, list);
|
||||||
AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
|
AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
|
||||||
dial->status = AST_DIAL_RESULT_ANSWERED;
|
set_state(dial, AST_DIAL_RESULT_ANSWERED);
|
||||||
break;
|
break;
|
||||||
case AST_CONTROL_BUSY:
|
case AST_CONTROL_BUSY:
|
||||||
if (option_verbose > 2)
|
if (option_verbose > 2)
|
||||||
@@ -360,7 +369,7 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel
|
|||||||
/*! \brief Helper function that handles control frames WITHOUT owner */
|
/*! \brief Helper function that handles control frames WITHOUT owner */
|
||||||
static void handle_frame_ownerless(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr)
|
static void handle_frame_ownerless(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr)
|
||||||
{
|
{
|
||||||
/* If we have no owner we can only update the status of the dial structure, so only look at control frames */
|
/* If we have no owner we can only update the state of the dial structure, so only look at control frames */
|
||||||
if (fr->frametype != AST_FRAME_CONTROL)
|
if (fr->frametype != AST_FRAME_CONTROL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -370,7 +379,7 @@ static void handle_frame_ownerless(struct ast_dial *dial, struct ast_dial_channe
|
|||||||
ast_verbose( VERBOSE_PREFIX_3 "%s answered\n", channel->owner->name);
|
ast_verbose( VERBOSE_PREFIX_3 "%s answered\n", channel->owner->name);
|
||||||
AST_LIST_REMOVE(&dial->channels, channel, list);
|
AST_LIST_REMOVE(&dial->channels, channel, list);
|
||||||
AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
|
AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
|
||||||
dial->status = AST_DIAL_RESULT_ANSWERED;
|
set_state(dial, AST_DIAL_RESULT_ANSWERED);
|
||||||
break;
|
break;
|
||||||
case AST_CONTROL_BUSY:
|
case AST_CONTROL_BUSY:
|
||||||
if (option_verbose > 2)
|
if (option_verbose > 2)
|
||||||
@@ -387,17 +396,17 @@ static void handle_frame_ownerless(struct ast_dial *dial, struct ast_dial_channe
|
|||||||
case AST_CONTROL_RINGING:
|
case AST_CONTROL_RINGING:
|
||||||
if (option_verbose > 2)
|
if (option_verbose > 2)
|
||||||
ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", channel->owner->name);
|
ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", channel->owner->name);
|
||||||
dial->status = AST_DIAL_RESULT_RINGING;
|
set_state(dial, AST_DIAL_RESULT_RINGING);
|
||||||
break;
|
break;
|
||||||
case AST_CONTROL_PROGRESS:
|
case AST_CONTROL_PROGRESS:
|
||||||
if (option_verbose > 2)
|
if (option_verbose > 2)
|
||||||
ast_verbose (VERBOSE_PREFIX_3 "%s is making progress\n", channel->owner->name);
|
ast_verbose (VERBOSE_PREFIX_3 "%s is making progress\n", channel->owner->name);
|
||||||
dial->status = AST_DIAL_RESULT_PROGRESS;
|
set_state(dial, AST_DIAL_RESULT_PROGRESS);
|
||||||
break;
|
break;
|
||||||
case AST_CONTROL_PROCEEDING:
|
case AST_CONTROL_PROCEEDING:
|
||||||
if (option_verbose > 2)
|
if (option_verbose > 2)
|
||||||
ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding\n", channel->owner->name);
|
ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding\n", channel->owner->name);
|
||||||
dial->status = AST_DIAL_RESULT_PROCEEDING;
|
set_state(dial, AST_DIAL_RESULT_PROCEEDING);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -414,18 +423,17 @@ static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_chann
|
|||||||
struct ast_dial_channel *channel = NULL;
|
struct ast_dial_channel *channel = NULL;
|
||||||
struct answer_exec_struct *answer_exec = NULL;
|
struct answer_exec_struct *answer_exec = NULL;
|
||||||
|
|
||||||
/* Switch dialing status to trying */
|
set_state(dial, AST_DIAL_RESULT_TRYING);
|
||||||
dial->status = AST_DIAL_RESULT_TRYING;
|
|
||||||
|
|
||||||
/* If the "always indicate ringing" option is set, change status to ringing and indicate to the owner if present */
|
/* If the "always indicate ringing" option is set, change state to ringing and indicate to the owner if present */
|
||||||
if (dial->options[AST_DIAL_OPTION_RINGING]) {
|
if (dial->options[AST_DIAL_OPTION_RINGING]) {
|
||||||
dial->status = AST_DIAL_RESULT_RINGING;
|
set_state(dial, AST_DIAL_RESULT_RINGING);
|
||||||
if (chan)
|
if (chan)
|
||||||
ast_indicate(chan, AST_CONTROL_RINGING);
|
ast_indicate(chan, AST_CONTROL_RINGING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Go into an infinite loop while we are trying */
|
/* Go into an infinite loop while we are trying */
|
||||||
while ((dial->status != AST_DIAL_RESULT_UNANSWERED) && (dial->status != AST_DIAL_RESULT_ANSWERED) && (dial->status != AST_DIAL_RESULT_HANGUP) && (dial->status != AST_DIAL_RESULT_TIMEOUT)) {
|
while ((dial->state != AST_DIAL_RESULT_UNANSWERED) && (dial->state != AST_DIAL_RESULT_ANSWERED) && (dial->state != AST_DIAL_RESULT_HANGUP) && (dial->state != AST_DIAL_RESULT_TIMEOUT)) {
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
struct ast_frame *fr = NULL;
|
struct ast_frame *fr = NULL;
|
||||||
|
|
||||||
@@ -442,9 +450,9 @@ static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_chann
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we have no outbound channels in progress, switch status to unanswered and stop */
|
/* If we have no outbound channels in progress, switch state to unanswered and stop */
|
||||||
if (!count) {
|
if (!count) {
|
||||||
dial->status = AST_DIAL_RESULT_UNANSWERED;
|
set_state(dial, AST_DIAL_RESULT_UNANSWERED);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,9 +477,9 @@ static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_chann
|
|||||||
|
|
||||||
/* Attempt to read in a frame */
|
/* Attempt to read in a frame */
|
||||||
if (!(fr = ast_read(who))) {
|
if (!(fr = ast_read(who))) {
|
||||||
/* If this is the caller then we switch status to hangup and stop */
|
/* If this is the caller then we switch state to hangup and stop */
|
||||||
if (chan && IS_CALLER(chan, who)) {
|
if (chan && IS_CALLER(chan, who)) {
|
||||||
dial->status = AST_DIAL_RESULT_HANGUP;
|
set_state(dial, AST_DIAL_RESULT_HANGUP);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ast_hangup(who);
|
ast_hangup(who);
|
||||||
@@ -490,7 +498,7 @@ static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_chann
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do post-processing from loop */
|
/* Do post-processing from loop */
|
||||||
if (dial->status == AST_DIAL_RESULT_ANSWERED) {
|
if (dial->state == AST_DIAL_RESULT_ANSWERED) {
|
||||||
/* Hangup everything except that which answered */
|
/* Hangup everything except that which answered */
|
||||||
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
|
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
|
||||||
if (!channel->owner || channel->owner == who)
|
if (!channel->owner || channel->owner == who)
|
||||||
@@ -501,7 +509,7 @@ static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_chann
|
|||||||
/* If ANSWER_EXEC is enabled as an option, execute application on answered channel */
|
/* If ANSWER_EXEC is enabled as an option, execute application on answered channel */
|
||||||
if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC)))
|
if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC)))
|
||||||
answer_exec_run(who, answer_exec->app, answer_exec->args);
|
answer_exec_run(who, answer_exec->app, answer_exec->args);
|
||||||
} else if (dial->status == AST_DIAL_RESULT_HANGUP) {
|
} else if (dial->state == AST_DIAL_RESULT_HANGUP) {
|
||||||
/* Hangup everything */
|
/* Hangup everything */
|
||||||
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
|
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
|
||||||
if (!channel->owner)
|
if (!channel->owner)
|
||||||
@@ -511,7 +519,7 @@ static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_chann
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dial->status;
|
return dial->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Dial async thread function */
|
/*! \brief Dial async thread function */
|
||||||
@@ -551,7 +559,7 @@ enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *cha
|
|||||||
|
|
||||||
/* If we are running async spawn a thread and send it away... otherwise block here */
|
/* If we are running async spawn a thread and send it away... otherwise block here */
|
||||||
if (async) {
|
if (async) {
|
||||||
dial->status = AST_DIAL_RESULT_TRYING;
|
set_state(dial, AST_DIAL_RESULT_TRYING);
|
||||||
/* Try to create a thread */
|
/* Try to create a thread */
|
||||||
if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) {
|
if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) {
|
||||||
/* Failed to create the thread - hangup all dialed channels and return failed */
|
/* Failed to create the thread - hangup all dialed channels and return failed */
|
||||||
@@ -574,16 +582,16 @@ struct ast_channel *ast_dial_answered(struct ast_dial *dial)
|
|||||||
if (!dial)
|
if (!dial)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return ((dial->status == AST_DIAL_RESULT_ANSWERED) ? AST_LIST_FIRST(&dial->channels)->owner : NULL);
|
return ((dial->state == AST_DIAL_RESULT_ANSWERED) ? AST_LIST_FIRST(&dial->channels)->owner : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Return status of dial
|
/*! \brief Return state of dial
|
||||||
* \note Returns the status of the dial attempt
|
* \note Returns the state of the dial attempt
|
||||||
* \param dial Dialing structure
|
* \param dial Dialing structure
|
||||||
*/
|
*/
|
||||||
enum ast_dial_result ast_dial_status(struct ast_dial *dial)
|
enum ast_dial_result ast_dial_state(struct ast_dial *dial)
|
||||||
{
|
{
|
||||||
return dial->status;
|
return dial->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Cancel async thread
|
/*! \brief Cancel async thread
|
||||||
@@ -613,7 +621,7 @@ enum ast_dial_result ast_dial_join(struct ast_dial *dial)
|
|||||||
/* Yay thread is all gone */
|
/* Yay thread is all gone */
|
||||||
dial->thread = AST_PTHREADT_NULL;
|
dial->thread = AST_PTHREADT_NULL;
|
||||||
|
|
||||||
return dial->status;
|
return dial->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Hangup channels
|
/*! \brief Hangup channels
|
||||||
@@ -809,3 +817,8 @@ int ast_dial_option_disable(struct ast_dial *dial, int num, enum ast_dial_option
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ast_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
|
||||||
|
{
|
||||||
|
dial->state_callback = callback;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user