[asterisk-commits] file: branch file/dialing_api r49489 - in
/team/file/dialing_api: apps/ inclu...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Thu Jan 4 12:17:20 MST 2007
Author: file
Date: Thu Jan 4 13:17:19 2007
New Revision: 49489
URL: http://svn.digium.com/view/asterisk?view=rev&rev=49489
Log:
Finish async dialing support in the API and add 'a' option to Dial2 which performs the dialing in an async fashion.
Modified:
team/file/dialing_api/apps/app_dial2.c
team/file/dialing_api/include/asterisk/dial.h
team/file/dialing_api/main/dial.c
Modified: team/file/dialing_api/apps/app_dial2.c
URL: http://svn.digium.com/view/asterisk/team/file/dialing_api/apps/app_dial2.c?view=diff&rev=49489&r1=49488&r2=49489
==============================================================================
--- team/file/dialing_api/apps/app_dial2.c (original)
+++ team/file/dialing_api/apps/app_dial2.c Thu Jan 4 13:17:19 2007
@@ -58,11 +58,95 @@
enum {
OPTION_RINGING = (1 << 0),
+ OPTION_ASYNC = (1 << 1),
} option_flags;
AST_APP_OPTIONS(app_opts,{
AST_APP_OPTION('r', OPTION_RINGING),
+ AST_APP_OPTION('a', OPTION_ASYNC),
});
+
+/* Sync running mode */
+static void run_sync(struct ast_channel *chan, struct ast_dial *dial)
+{
+ struct ast_bridge_config bridge_config;
+ struct ast_channel *answered = NULL;
+
+ /* Wipe out bridge configuration information */
+ memset(&bridge_config, 0, sizeof(bridge_config));
+
+ /* If the dial attempt failed or was not answered, bail out */
+ if (ast_dial_run(dial, chan, 0) != AST_DIAL_RESULT_ANSWERED)
+ return;
+
+ /* If we can't get the answered channel (by some weird fluke), bail out */
+ if (!(answered = ast_dial_answered(dial)))
+ return;
+
+ /* We have everything we need... bridge the two channels */
+ ast_bridge_call(chan, answered, &bridge_config);
+
+ return;
+}
+
+/* Async running mode */
+static void run_async(struct ast_channel *chan, struct ast_dial *dial)
+{
+ struct ast_bridge_config bridge_config;
+ struct ast_channel *answered = NULL;
+ enum ast_dial_result status = AST_DIAL_RESULT_TRYING, old_status = AST_DIAL_RESULT_TRYING;
+ struct ast_frame *fr = NULL;
+
+ /* Wipe out bridge configuration information */
+ memset(&bridge_config, 0, sizeof(bridge_config));
+
+ /* Start dial attempt in async mode */
+ if (ast_dial_run(dial, chan, 1) != AST_DIAL_RESULT_TRYING)
+ return;
+
+ /* Go into a loop checking our owner channel, and peeking at the dial status */
+ for (;;) {
+ /* Wait for frames from the owner to a maximum of 20ms */
+ if (ast_waitfor(chan, 20) > 0) {
+ /* Process frame */
+ if (!(fr = ast_read(chan))) {
+ /* Abort execution of async dial */
+ ast_dial_join(dial);
+ break;
+ }
+ ast_frfree(fr);
+ }
+
+ /* Check status of dialing attempt */
+ status = ast_dial_status(dial);
+
+ /* Process dial status */
+ if (status == AST_DIAL_RESULT_ANSWERED) {
+ break;
+ } else if (old_status != status) {
+ if (status == AST_DIAL_RESULT_RINGING)
+ ast_indicate(chan, AST_CONTROL_RINGING);
+ else if (status == AST_DIAL_RESULT_PROGRESS)
+ ast_indicate(chan, AST_CONTROL_PROGRESS);
+ else if (status == AST_DIAL_RESULT_PROCEEDING)
+ ast_indicate(chan, AST_CONTROL_PROCEEDING);
+ old_status = status;
+ }
+ }
+
+ /* If the status is not answered, bail out */
+ if (status != AST_DIAL_RESULT_ANSWERED)
+ return;
+
+ /* If we can't get the answered channel (by some weird fluke), bail out */
+ if (!(answered = ast_dial_answered(dial)))
+ return;
+
+ /* We have everything we need... bridge the two channels */
+ ast_bridge_call(chan, answered, &bridge_config);
+
+ return;
+}
static int dial2_exec(struct ast_channel *chan, void *data)
{
@@ -71,8 +155,6 @@
struct ast_module_user *u;
struct ast_dial *dial = NULL;
char *tmp = NULL, *tmp2 = NULL, *tech = NULL, *device = NULL;
- struct ast_channel *answered = NULL;
- struct ast_bridge_config bridge_config;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(dummy);
AST_APP_ARG(options);
@@ -117,11 +199,11 @@
ast_dial_append(dial, tech, device);
}
- memset(&bridge_config, 0, sizeof(bridge_config));
-
/* Attempt to dial all the channels and bridge to the one that answered */
- if ((ast_dial_run(dial, chan, 0) == AST_DIAL_RESULT_ANSWERED) && (answered = ast_dial_answered(dial)))
- ast_bridge_call(chan, answered, &bridge_config);
+ if (ast_test_flag(&flags, OPTION_ASYNC))
+ run_async(chan, dial);
+ else
+ run_sync(chan, dial);
/* Hangup all calls in the dialing structure */
ast_dial_hangup(dial);
Modified: team/file/dialing_api/include/asterisk/dial.h
URL: http://svn.digium.com/view/asterisk/team/file/dialing_api/include/asterisk/dial.h?view=diff&rev=49489&r1=49488&r2=49489
==============================================================================
--- team/file/dialing_api/include/asterisk/dial.h (original)
+++ team/file/dialing_api/include/asterisk/dial.h Thu Jan 4 13:17:19 2007
@@ -83,6 +83,12 @@
*/
enum ast_dial_result ast_dial_status(struct ast_dial *dial);
+/*! \brief Cancel async thread
+ * \note Cancel a running async thread
+ * \param dial Dialing structure
+ */
+enum ast_dial_result ast_dial_join(struct ast_dial *dial);
+
/*! \brief Hangup channels
* \note Hangup all active channels
* \param dial Dialing structure
Modified: team/file/dialing_api/main/dial.c
URL: http://svn.digium.com/view/asterisk/team/file/dialing_api/main/dial.c?view=diff&rev=49489&r1=49488&r2=49489
==============================================================================
--- team/file/dialing_api/main/dial.c (original)
+++ team/file/dialing_api/main/dial.c Thu Jan 4 13:17:19 2007
@@ -355,7 +355,7 @@
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)) {
int pos = 0;
struct ast_frame *fr = NULL;
-
+
/* Set up channel structure array */
pos = count = 0;
if (chan)
@@ -376,10 +376,15 @@
}
/* Wait for frames from channels */
- if (!(who = ast_waitfor_n(cs, pos, &timeout))) {
- /* We need to handle timeouts here when it is implemented */
+ who = ast_waitfor_n(cs, pos, &timeout);
+
+ /* Check to see if our thread is being cancelled */
+ if (dial->thread == AST_PTHREADT_STOP)
+ break;
+
+ /* If we are not being cancelled and we have no channel, then timeout was tripped */
+ if (!who)
continue;
- }
/* Find relative dial channel */
if (!chan || !IS_CALLER(chan, who))
@@ -416,7 +421,7 @@
ast_hangup(channel->owner);
channel->owner = NULL;
}
- } else {
+ } else if (dial->status == AST_DIAL_RESULT_HANGUP) {
/* Hangup everything */
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
if (!channel->owner)
@@ -493,6 +498,36 @@
*/
enum ast_dial_result ast_dial_status(struct ast_dial *dial)
{
+ return dial->status;
+}
+
+/*! \brief Cancel async thread
+ * \note Cancel a running async thread
+ * \param dial Dialing structure
+ */
+enum ast_dial_result ast_dial_join(struct ast_dial *dial)
+{
+ pthread_t thread;
+
+ /* If the dial structure is not running in async, return failed */
+ if (dial->thread == AST_PTHREADT_NULL)
+ return AST_DIAL_RESULT_FAILED;
+
+ /* Record thread */
+ thread = dial->thread;
+
+ /* Stop the thread */
+ dial->thread = AST_PTHREADT_STOP;
+
+ /* Now we signal it with SIGURG so it will break out of it's waitfor */
+ pthread_kill(thread, SIGURG);
+
+ /* Finally wait for the thread to exit */
+ pthread_join(thread, NULL);
+
+ /* Yay thread is all gone */
+ dial->thread = AST_PTHREADT_NULL;
+
return dial->status;
}
More information about the asterisk-commits
mailing list