[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