[asterisk-commits] mmichelson: trunk r370951 - in /trunk: ./ apps/ include/asterisk/ main/ pbx/ ...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Aug 8 17:39:48 CDT 2012


Author: mmichelson
Date: Wed Aug  8 17:39:40 2012
New Revision: 370951

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=370951
Log:
Allow support for early media on AMI originates and call files.

This is based on the work done by Olle Johansson on review board.

The idea is that the channel specified in an AMI originate or call
file is typically not connected to the outgoing extension until the
channel has been answered. With this change, an EarlyMedia header can
be specified for AMI originates and an early_media option can
be specified in call files. With this option set, once early media is
received on a channel, it will be connected with the outgoing extension.

(closes issue ASTERISK-18644)
Reported by Olle Johansson

Review: https://reviewboard.asterisk.org/r/1472


Modified:
    trunk/CHANGES
    trunk/apps/app_originate.c
    trunk/include/asterisk/channel.h
    trunk/include/asterisk/pbx.h
    trunk/main/channel.c
    trunk/main/manager.c
    trunk/main/pbx.c
    trunk/pbx/pbx_spool.c
    trunk/res/res_clioriginate.c

Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=370951&r1=370950&r2=370951
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Wed Aug  8 17:39:40 2012
@@ -425,6 +425,9 @@
  * Asterisk can now use a system-provided NetBSD editline library (libedit) if it
    is available.
 
+ * Call files now support the "early_media" option to connect with an outgoing
+   extension when early media is received.
+
 AGI
 ------------------
  * A new channel variable, AGIEXITONHANGUP, has been added which allows
@@ -438,6 +441,10 @@
 
 AMI (Asterisk Manager Interface)
 ------------------
+ * The originate action now has an option "EarlyMedia" that enables the
+   call to bridge when we get early media in the call. Previously,
+   early media was disregarded always when originating calls using AMI.
+
  * Added setvar= option to manager accounts (much like sip.conf)
 
  * Originate now generates an error response if the extension given is not found

Modified: trunk/apps/app_originate.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_originate.c?view=diff&rev=370951&r1=370950&r2=370951
==============================================================================
--- trunk/apps/app_originate.c (original)
+++ trunk/apps/app_originate.c Wed Aug  8 17:39:40 2012
@@ -178,7 +178,7 @@
 
 		ast_pbx_outgoing_exten(chantech, cap_slin, chandata,
 				timeout * 1000, args.arg1, exten, priority, &outgoing_status, 0, NULL,
-				NULL, NULL, NULL, NULL);
+				NULL, NULL, NULL, NULL, 0);
 	} else if (!strcasecmp(args.type, "app")) {
 		ast_debug(1, "Originating call to '%s/%s' and connecting them to %s(%s)\n",
 				chantech, chandata, args.arg1, S_OR(args.arg2, ""));

Modified: trunk/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/channel.h?view=diff&rev=370951&r1=370950&r2=370951
==============================================================================
--- trunk/include/asterisk/channel.h (original)
+++ trunk/include/asterisk/channel.h Wed Aug  8 17:39:40 2012
@@ -907,6 +907,7 @@
 	const char *context;
 	const char *exten;
 	int priority;
+	int connect_on_early_media;	/* If set, treat session progress as answer */
 	const char *cid_num;
 	const char *cid_name;
 	const char *account;

Modified: trunk/include/asterisk/pbx.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/pbx.h?view=diff&rev=370951&r1=370950&r2=370951
==============================================================================
--- trunk/include/asterisk/pbx.h (original)
+++ trunk/include/asterisk/pbx.h Wed Aug  8 17:39:40 2012
@@ -1010,7 +1010,7 @@
 
 /*! Synchronously or asynchronously make an outbound call and send it to a
    particular extension */
-int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel);
+int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media);
 
 /*! Synchronously or asynchronously make an outbound call and send it to a
    particular application with given extension */

Modified: trunk/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/channel.c?view=diff&rev=370951&r1=370950&r2=370951
==============================================================================
--- trunk/main/channel.c (original)
+++ trunk/main/channel.c Wed Aug  8 17:39:40 2012
@@ -5620,8 +5620,14 @@
 					ast_channel_hangupcause_hash_set(chan, f->data.ptr, f->datalen);
 					break;
 
+				case AST_CONTROL_PROGRESS:
+					if (oh && oh->connect_on_early_media) {
+						*outstate = f->subclass.integer;
+						timeout = 0;		/* trick to force exit from the while() */
+						break;
+					}
+					/* Fallthrough */
 				/* Ignore these */
-				case AST_CONTROL_PROGRESS:
 				case AST_CONTROL_PROCEEDING:
 				case AST_CONTROL_HOLD:
 				case AST_CONTROL_UNHOLD:

Modified: trunk/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/manager.c?view=diff&rev=370951&r1=370950&r2=370951
==============================================================================
--- trunk/main/manager.c (original)
+++ trunk/main/manager.c Wed Aug  8 17:39:40 2012
@@ -464,6 +464,9 @@
 			</parameter>
 			<parameter name="Account">
 				<para>Account code.</para>
+			</parameter>
+			<parameter name="EarlyMedia">
+				<para>Set to <literal>true</literal> to force call bridge on early media..</para>
 			</parameter>
 			<parameter name="Async">
 				<para>Set to <literal>true</literal> for fast origination.</para>
@@ -3915,6 +3918,7 @@
 struct fast_originate_helper {
 	int timeout;
 	struct ast_format_cap *cap;				/*!< Codecs used for a call */
+	int early_media;
 	AST_DECLARE_STRING_FIELDS (
 		AST_STRING_FIELD(tech);
 		/*! data can contain a channel name, extension number, username, password, etc. */
@@ -3966,7 +3970,7 @@
 			in->timeout, in->context, in->exten, in->priority, &reason, 1,
 			S_OR(in->cid_num, NULL),
 			S_OR(in->cid_name, NULL),
-			in->vars, in->account, &chan);
+			in->vars, in->account, &chan, in->early_media);
 	}
 	/* Any vars memory was passed to the ast_pbx_outgoing_xxx() calls. */
 	in->vars = NULL;
@@ -4245,6 +4249,7 @@
 	const char *async = astman_get_header(m, "Async");
 	const char *id = astman_get_header(m, "ActionID");
 	const char *codecs = astman_get_header(m, "Codecs");
+	const char *early_media = astman_get_header(m, "Earlymedia");
 	struct ast_variable *vars = NULL;
 	char *tech, *data;
 	char *l = NULL, *n = NULL;
@@ -4257,6 +4262,7 @@
 	struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
 	struct ast_format tmp_fmt;
 	pthread_t th;
+	int bridge_early = 0;
 
 	if (!cap) {
 		astman_send_error(s, m, "Internal Error. Memory allocation failure.");
@@ -4358,6 +4364,9 @@
 			}
 		}
 	}
+
+	/* For originate async - we can bridge in early media stage */
+	bridge_early = ast_true(early_media);
 
 	if (ast_true(async)) {
 		struct fast_originate_helper *fast;
@@ -4384,6 +4393,7 @@
 			fast->cap = cap;
 			cap = NULL; /* transfered originate helper the capabilities structure.  It is now responsible for freeing it. */
 			fast->timeout = to;
+			fast->early_media = bridge_early;
 			fast->priority = pi;
 			if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) {
 				destroy_fast_originate_helper(fast);
@@ -4397,7 +4407,7 @@
 		/* Any vars memory was passed to ast_pbx_outgoing_app(). */
 	} else {
 		if (exten && context && pi) {
-			res = ast_pbx_outgoing_exten(tech, cap, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
+			res = ast_pbx_outgoing_exten(tech, cap, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL, bridge_early);
 			/* Any vars memory was passed to ast_pbx_outgoing_exten(). */
 		} else {
 			astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");

Modified: trunk/main/pbx.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/pbx.c?view=diff&rev=370951&r1=370950&r2=370951
==============================================================================
--- trunk/main/pbx.c (original)
+++ trunk/main/pbx.c Wed Aug  8 17:39:40 2012
@@ -9559,6 +9559,7 @@
 	int timeout;
 	char app[AST_MAX_EXTENSION];
 	char appdata[1024];
+	int early_media;			/* Connect the bridge if early media arrives, don't wait for answer */
 };
 
 static void *async_wait(void *data)
@@ -9569,6 +9570,7 @@
 	int res;
 	struct ast_frame *f;
 	struct ast_app *app;
+	int have_early_media = 0;
 
 	if (chan) {
 		struct ast_callid *callid = ast_channel_callid(chan);
@@ -9593,10 +9595,18 @@
 				ast_frfree(f);
 				break;
 			}
+			if (as->early_media && f->subclass.integer == AST_CONTROL_PROGRESS) {
+				have_early_media = 1;
+				ast_frfree(f);
+				break;
+			}
 		}
 		ast_frfree(f);
 	}
-	if (ast_channel_state(chan) == AST_STATE_UP) {
+	if (ast_channel_state(chan) == AST_STATE_UP || have_early_media) {
+		if (have_early_media) {
+			ast_debug(2, "Activating pbx since we have early media \n");
+		}
 		if (!ast_strlen_zero(as->app)) {
 			app = pbx_findapp(as->app);
 			if (app) {
@@ -9657,7 +9667,7 @@
 	return 0;  /* success */
 }
 
-int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
+int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, int early_media)
 {
 	struct ast_channel *chan;
 	struct async_stat *as;
@@ -9665,6 +9675,8 @@
 	int callid_created = 0;
 	int res = -1, cdr_res = -1;
 	struct outgoing_helper oh;
+
+	oh.connect_on_early_media = early_media;
 
 	callid_created = ast_callid_threadstorage_auto(&callid);
 
@@ -9695,9 +9707,9 @@
 				}
 			}
 
-			if (ast_channel_state(chan) == AST_STATE_UP) {
+			if (ast_channel_state(chan) == AST_STATE_UP || (early_media && *reason == AST_CONTROL_PROGRESS)) {
 					res = 0;
-				ast_verb(4, "Channel %s was answered.\n", ast_channel_name(chan));
+				ast_verb(4, "Channel %s %s\n", ast_channel_name(chan), ast_channel_state(chan) == AST_STATE_UP ? "was answered" : "got early media");
 
 				if (synchronous > 1) {
 					if (channel)

Modified: trunk/pbx/pbx_spool.c
URL: http://svnview.digium.com/svn/asterisk/trunk/pbx/pbx_spool.c?view=diff&rev=370951&r1=370950&r2=370951
==============================================================================
--- trunk/pbx/pbx_spool.c (original)
+++ trunk/pbx/pbx_spool.c Wed Aug  8 17:39:40 2012
@@ -67,6 +67,8 @@
 	SPOOL_FLAG_ALWAYS_DELETE = (1 << 0),
 	/* Don't unlink the call file after processing, move in qdonedir */
 	SPOOL_FLAG_ARCHIVE = (1 << 1),
+	/* Connect the channel with the outgoing extension once early media is received */
+	SPOOL_FLAG_EARLY_MEDIA = (1 << 2),
 };
 
 static char qdir[255];
@@ -253,6 +255,8 @@
 					ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ALWAYS_DELETE);
 				} else if (!strcasecmp(buf, "archive")) {
 					ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ARCHIVE);
+				} else if (!strcasecmp(buf, "early_media")) {
+					ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_EARLY_MEDIA);
 				} else {
 					ast_log(LOG_WARNING, "Unknown keyword '%s' at line %d of %s\n", buf, lineno, fn);
 				}
@@ -357,7 +361,8 @@
 		ast_verb(3, "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
 		res = ast_pbx_outgoing_exten(o->tech, o->capabilities, o->dest,
 			o->waittime * 1000, o->context, o->exten, o->priority, &reason,
-			2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
+			2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL,
+			ast_test_flag(&o->options, SPOOL_FLAG_EARLY_MEDIA));
 		o->vars = NULL;
 	}
 	if (res) {

Modified: trunk/res/res_clioriginate.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_clioriginate.c?view=diff&rev=370951&r1=370950&r2=370951
==============================================================================
--- trunk/res/res_clioriginate.c (original)
+++ trunk/res/res_clioriginate.c Wed Aug  8 17:39:40 2012
@@ -119,7 +119,7 @@
 		return CLI_FAILURE;
 	}
 	ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
-	ast_pbx_outgoing_exten(chantech, cap, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 0, NULL, NULL, NULL, NULL, NULL);
+	ast_pbx_outgoing_exten(chantech, cap, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 0, NULL, NULL, NULL, NULL, NULL, 0);
 	cap = ast_format_cap_destroy(cap);
 
 	return CLI_SUCCESS;




More information about the asterisk-commits mailing list