[asterisk-commits] rmudgett: trunk r412583 - in /trunk: ./ apps/ include/asterisk/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Apr 18 11:44:54 CDT 2014


Author: rmudgett
Date: Fri Apr 18 11:44:48 2014
New Revision: 412583

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=412583
Log:
Originated calls: Fix several originate call problems.

* Restore the reason value set by pbx_outgoing_attempt() to use
AST_CONTROL_xxx values as all the consumers were expecting rather than
cause codes.

* Fixed the dial routines to set cause codes for more than just
ast_request() so pbx_outgoing_attempt() reason codes will function.

* Fix inconsistent locked_channel return status in pbx_outgoing_attempt().
The chanel may not have been locked or the channel may have been a stale
pointer.

* Fixed the OutgoingSpoolFailed channel to run dialplan whenever the
dialing fails for an originate exten and 1 < synchronous.

* Fix incorrect ast_cond_wait() usage in pbx_outgoing_attempt().
Indroduced by issue ASTERISK-22212 patch.

* Made struct pbx_outgoing use the ao2 lock instead of its own lock for
the cond wait mutex.  No sense in having two locks associated with the
same struct when only one is needed.

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

Merged revisions 412581 from http://svn.asterisk.org/svn/asterisk/branches/12

Modified:
    trunk/   (props changed)
    trunk/apps/app_originate.c
    trunk/include/asterisk/pbx.h
    trunk/main/dial.c
    trunk/main/pbx.c

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-12-merged' - no diff available.

Modified: trunk/apps/app_originate.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_originate.c?view=diff&rev=412583&r1=412582&r2=412583
==============================================================================
--- trunk/apps/app_originate.c (original)
+++ trunk/apps/app_originate.c Fri Apr 18 11:44:48 2014
@@ -177,14 +177,14 @@
 				chantech, chandata, args.arg1, exten, priority);
 
 		ast_pbx_outgoing_exten(chantech, cap_slin, chandata,
-				timeout * 1000, args.arg1, exten, priority, &outgoing_status, 0, NULL,
+				timeout * 1000, args.arg1, exten, priority, &outgoing_status, 1, NULL,
 				NULL, NULL, NULL, NULL, 0, NULL);
 	} 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, ""));
 
 		ast_pbx_outgoing_app(chantech, cap_slin, chandata,
-				timeout * 1000, args.arg1, args.arg2, &outgoing_status, 0, NULL,
+				timeout * 1000, args.arg1, args.arg2, &outgoing_status, 1, NULL,
 				NULL, NULL, NULL, NULL, NULL);
 	} else {
 		ast_log(LOG_ERROR, "Incorrect type, it should be 'exten' or 'app': %s\n",

Modified: trunk/include/asterisk/pbx.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/pbx.h?view=diff&rev=412583&r1=412582&r2=412583
==============================================================================
--- trunk/include/asterisk/pbx.h (original)
+++ trunk/include/asterisk/pbx.h Fri Apr 18 11:44:48 2014
@@ -1102,7 +1102,8 @@
  */
 int ast_async_goto_by_name(const char *chan, const char *context, const char *exten, int priority);
 
-/*! \brief Synchronously or asynchronously make an outbound call and send it to a
+/*!
+ * \brief Synchronously or asynchronously make an outbound call and send it to a
  * particular extension
  *
  * \param type The channel technology to create
@@ -1112,27 +1113,34 @@
  * \param context The destination context for the outbound channel
  * \param exten The destination extension for the outbound channel
  * \param priority The destination priority for the outbound channel
- * \param reason Optional. If provided, the hangup cause code of the outbound channel if
- *  it failed
- * \param sync If non-zero, block until the outbound channel answers
+ * \param reason Optional.  If provided, the dialed status of the outgoing channel.
+ *        Codes are AST_CONTROL_xxx values.  Valid only if synchronous is non-zero.
+ * \param synchronous If zero then don't wait for anything.
+ *        If one then block until the outbound channel answers or the call fails.
+ *        If greater than one then wait for the call to complete or if the call doesn't
+ *        answer and failed at context exists then run a channel named OutgoingSpoolFailed
+ *        at failed at context.
  * \param cid_num The caller ID number to set on the outbound channel
  * \param cid_name The caller ID name to set on the outbound channel
  * \param vars Variables to set on the outbound channel
  * \param account The accountcode for the outbound channel
- * \param locked_channel Optional. The outbound channel that was created. This is returned
- *  both locked and reference bumped. If a caller provides a channel parameter, it must
- *  unlock the channel and decrement the reference count.
- *  \param assignedid Optional. The uniqueid to assign the channel that was created.
- *  \param assignedid2 Optional. The uniqueid to assign the second local channel.
- * \param early_media If non-zero, allow early-media on the originated channel
+ * \param locked_channel Optional.  The outbound channel that was created if success
+ *        is returned.  Otherwise it is set to NULL.  This is returned both locked
+ *        and reference bumped.
+ * \param early_media If non-zero the channel "answers" when progress is indicated.
+ * \param assignedids Optional. The uniqueid(s) to assign the channel(s) that are created.
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
  */
 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,
+	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 **locked_channel, int early_media,
 	const struct ast_assigned_ids *assignedids);
 
-/*! \brief Synchronously or asynchronously make an outbound call and execute an
+/*!
+ * \brief Synchronously or asynchronously make an outbound call and execute an
  *  application on the channel.
  *
  * Note that when the application stops executing, the channel is hungup.
@@ -1143,23 +1151,27 @@
  * \param timeout How long we should attempt to dial the outbound channel
  * \param app The name of the application to execute
  * \param appdata Data to pass to the application
- * \param reason Optional. If provided, the hangup cause code of the outbound channel if
- *  it failed
- * \param sync If non-zero, block until the outbound channel answers
+ * \param reason Optional.  If provided, the dialed status of the outgoing channel.
+ *        Codes are AST_CONTROL_xxx values.  Valid only if synchronous is non-zero.
+ * \param synchronous If zero then don't wait for anything.
+ *        If one then block until the outbound channel answers or the call fails.
+ *        If greater than one then wait for the call to complete.
  * \param cid_num The caller ID number to set on the outbound channel
  * \param cid_name The caller ID name to set on the outbound channel
  * \param vars Variables to set on the outbound channel
  * \param account The accountcode for the outbound channel
- * \param locked_channel Optional. The outbound channel that was created. This is returned
- *  \param assignedid Optional. The uniqueid to assign the channel that was created.
- *  \param assignedid2 Optional. The uniqueid to assign the second local channel.
- *  both locked and reference bumped. If a caller provides a channel parameter, it must
- *  unlock the channel and decrement the reference count.
+ * \param locked_channel Optional.  The outbound channel that was created if success
+ *        is returned.  Otherwise it is set to NULL.  This is returned both locked
+ *        and reference bumped.
+ * \param assignedids Optional. The uniqueid(s) to assign the channel(s) that are created.
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
  */
 int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr,
-    int timeout, const char *app, const char *appdata, 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 timeout, const char *app, const char *appdata, int *reason, int synchronous,
+	const char *cid_num, const char *cid_name, struct ast_variable *vars,
+	const char *account, struct ast_channel **locked_channel,
 	const struct ast_assigned_ids *assignedids);
 
 /*!

Modified: trunk/main/dial.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/dial.c?view=diff&rev=412583&r1=412582&r2=412583
==============================================================================
--- trunk/main/dial.c (original)
+++ trunk/main/dial.c Fri Apr 18 11:44:48 2014
@@ -541,12 +541,14 @@
 			ast_verb(3, "%s is busy\n", ast_channel_name(channel->owner));
 			ast_channel_publish_dial(chan, channel->owner, channel->device, "BUSY");
 			ast_hangup(channel->owner);
+			channel->cause = AST_CAUSE_USER_BUSY;
 			channel->owner = NULL;
 			break;
 		case AST_CONTROL_CONGESTION:
 			ast_verb(3, "%s is circuit-busy\n", ast_channel_name(channel->owner));
 			ast_channel_publish_dial(chan, channel->owner, channel->device, "CONGESTION");
 			ast_hangup(channel->owner);
+			channel->cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
 			channel->owner = NULL;
 			break;
 		case AST_CONTROL_INCOMPLETE:
@@ -593,7 +595,7 @@
 			break;
 		case AST_CONTROL_HOLD:
 			ast_verb(3, "Call on %s placed on hold\n", ast_channel_name(chan));
-			ast_indicate(chan, AST_CONTROL_HOLD);
+			ast_indicate_data(chan, AST_CONTROL_HOLD, fr->data.ptr, fr->datalen);
 			break;
 		case AST_CONTROL_UNHOLD:
 			ast_verb(3, "Call on %s left from hold\n", ast_channel_name(chan));
@@ -613,8 +615,6 @@
 			break;
 		}
 	}
-
-	return;
 }
 
 /*! \brief Helper function that handles control frames WITHOUT owner */
@@ -638,12 +638,25 @@
 		ast_verb(3, "%s is busy\n", ast_channel_name(channel->owner));
 		ast_channel_publish_dial(NULL, channel->owner, channel->device, "BUSY");
 		ast_hangup(channel->owner);
+		channel->cause = AST_CAUSE_USER_BUSY;
 		channel->owner = NULL;
 		break;
 	case AST_CONTROL_CONGESTION:
 		ast_verb(3, "%s is circuit-busy\n", ast_channel_name(channel->owner));
 		ast_channel_publish_dial(NULL, channel->owner, channel->device, "CONGESTION");
 		ast_hangup(channel->owner);
+		channel->cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
+		channel->owner = NULL;
+		break;
+	case AST_CONTROL_INCOMPLETE:
+		/*
+		 * Nothing to do but abort the call since we have no
+		 * controlling channel to ask for more digits.
+		 */
+		ast_verb(3, "%s dialed Incomplete extension %s\n",
+			ast_channel_name(channel->owner), ast_channel_exten(channel->owner));
+		ast_hangup(channel->owner);
+		channel->cause = AST_CAUSE_UNALLOCATED;
 		channel->owner = NULL;
 		break;
 	case AST_CONTROL_RINGING:
@@ -661,8 +674,6 @@
 	default:
 		break;
 	}
-
-	return;
 }
 
 /*! \brief Helper function to handle when a timeout occurs on dialing attempt */
@@ -686,6 +697,7 @@
 	AST_LIST_TRAVERSE(&dial->channels, channel, list) {
 		if (dial->state == AST_DIAL_RESULT_TIMEOUT || diff >= channel->timeout) {
 			ast_hangup(channel->owner);
+			channel->cause = AST_CAUSE_NO_ANSWER;
 			channel->owner = NULL;
 		} else if ((lowest_timeout == -1) || (lowest_timeout > channel->timeout)) {
 			lowest_timeout = channel->timeout;
@@ -835,6 +847,7 @@
 				ast_poll_channel_del(chan, channel->owner);
 			ast_channel_publish_dial(chan, channel->owner, channel->device, "CANCEL");
 			ast_hangup(channel->owner);
+			channel->cause = AST_CAUSE_ANSWERED_ELSEWHERE;
 			channel->owner = NULL;
 		}
 		AST_LIST_UNLOCK(&dial->channels);
@@ -859,6 +872,7 @@
 				ast_poll_channel_del(chan, channel->owner);
 			ast_channel_publish_dial(chan, channel->owner, channel->device, "CANCEL");
 			ast_hangup(channel->owner);
+			channel->cause = AST_CAUSE_NORMAL_CLEARING;
 			channel->owner = NULL;
 		}
 		AST_LIST_UNLOCK(&dial->channels);

Modified: trunk/main/pbx.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/pbx.c?view=diff&rev=412583&r1=412582&r2=412583
==============================================================================
--- trunk/main/pbx.c (original)
+++ trunk/main/pbx.c Fri Apr 18 11:44:48 2014
@@ -10092,8 +10092,6 @@
 struct pbx_outgoing {
 	/*! \brief Dialing structure being used */
 	struct ast_dial *dial;
-	/*! \brief Mutex lock for synchronous dialing */
-	ast_mutex_t lock;
 	/*! \brief Condition for synchronous dialing */
 	ast_cond_t cond;
 	/*! \brief Application to execute */
@@ -10123,7 +10121,6 @@
 		ast_dial_destroy(outgoing->dial);
 	}
 
-	ast_mutex_destroy(&outgoing->lock);
 	ast_cond_destroy(&outgoing->cond);
 
 	ast_free(outgoing->appdata);
@@ -10136,12 +10133,12 @@
 	enum ast_dial_result res;
 
 	/* Notify anyone interested that dialing is complete */
-	ast_mutex_lock(&outgoing->lock);
 	res = ast_dial_run(outgoing->dial, NULL, 0);
+	ao2_lock(outgoing);
 	outgoing->dial_res = res;
 	outgoing->dialed = 1;
 	ast_cond_signal(&outgoing->cond);
-	ast_mutex_unlock(&outgoing->lock);
+	ao2_unlock(outgoing);
 
 	/* If the outgoing leg was not answered we can immediately return and go no further */
 	if (res != AST_DIAL_RESULT_ANSWERED) {
@@ -10182,10 +10179,10 @@
 	}
 
 	/* Notify anyone else again that may be interested that execution is complete */
-	ast_mutex_lock(&outgoing->lock);
+	ao2_lock(outgoing);
 	outgoing->executed = 1;
 	ast_cond_signal(&outgoing->cond);
-	ast_mutex_unlock(&outgoing->lock);
+	ao2_unlock(outgoing);
 
 	return NULL;
 }
@@ -10209,21 +10206,69 @@
 	ast_queue_control(channel, AST_CONTROL_ANSWER);
 }
 
-static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context,
-	const char *exten, int priority, const char *app, const char *appdata, 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, const struct ast_assigned_ids *assignedids)
-{
-	RAII_VAR(struct pbx_outgoing *, outgoing, ao2_alloc(sizeof(*outgoing), pbx_outgoing_destroy), ao2_cleanup);
+/*!
+ * \brief Attempt to convert disconnect cause to old originate reason.
+ *
+ * \todo XXX The old originate reasons need to be trashed and replaced
+ * with normal disconnect cause codes if the call was not answered.
+ * The internal consumers of the reason values would also need to be
+ * updated: app_originate, call files, and AMI OriginateResponse.
+ */
+static enum ast_control_frame_type pbx_dial_reason(enum ast_dial_result dial_result, int cause)
+{
+	enum ast_control_frame_type pbx_reason;
+
+	if (dial_result == AST_DIAL_RESULT_ANSWERED) {
+		/* Remote end answered. */
+		pbx_reason = AST_CONTROL_ANSWER;
+	} else if (dial_result == AST_DIAL_RESULT_HANGUP) {
+		/* Caller hungup */
+		pbx_reason = AST_CONTROL_HANGUP;
+	} else {
+		switch (cause) {
+		case AST_CAUSE_USER_BUSY:
+			pbx_reason = AST_CONTROL_BUSY;
+			break;
+		case AST_CAUSE_CALL_REJECTED:
+		case AST_CAUSE_NETWORK_OUT_OF_ORDER:
+		case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
+		case AST_CAUSE_NORMAL_TEMPORARY_FAILURE:
+		case AST_CAUSE_SWITCH_CONGESTION:
+		case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+			pbx_reason = AST_CONTROL_CONGESTION;
+			break;
+		case AST_CAUSE_ANSWERED_ELSEWHERE:
+		case AST_CAUSE_NO_ANSWER:
+			/* Remote end was ringing (but isn't anymore) */
+			pbx_reason = AST_CONTROL_RINGING;
+			break;
+		case AST_CAUSE_UNALLOCATED:
+		default:
+			/* Call Failure (not BUSY, and not NO_ANSWER, maybe Circuit busy or down?) */
+			pbx_reason = 0;
+			break;
+		}
+	}
+
+	return pbx_reason;
+}
+
+static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap,
+	const char *addr, int timeout, const char *context, const char *exten, int priority,
+	const char *app, const char *appdata, int *reason, int synchronous,
+	const char *cid_num, const char *cid_name, struct ast_variable *vars,
+	const char *account, struct ast_channel **locked_channel, int early_media,
+	const struct ast_assigned_ids *assignedids)
+{
+	RAII_VAR(struct pbx_outgoing *, outgoing, NULL, ao2_cleanup);
 	struct ast_channel *dialed;
 	pthread_t thread;
 
+	outgoing = ao2_alloc(sizeof(*outgoing), pbx_outgoing_destroy);
 	if (!outgoing) {
 		return -1;
 	}
-
-	if (channel) {
-		*channel = NULL;
-	}
+	ast_cond_init(&outgoing->cond, NULL);
 
 	if (!ast_strlen_zero(app)) {
 		ast_copy_string(outgoing->app, app, sizeof(outgoing->app));
@@ -10245,6 +10290,10 @@
 	ast_dial_set_global_timeout(outgoing->dial, timeout);
 
 	if (ast_dial_prerun(outgoing->dial, NULL, cap)) {
+		if (synchronous && reason) {
+			*reason = pbx_dial_reason(AST_DIAL_RESULT_FAILED,
+				ast_dial_reason(outgoing->dial, 0));
+		}
 		return -1;
 	}
 
@@ -10257,7 +10306,6 @@
 	if (vars) {
 		ast_set_variables(dialed, vars);
 	}
-
 	if (account) {
 		ast_channel_accountcode_set(dialed, account);
 	}
@@ -10295,107 +10343,148 @@
 		ast_dial_set_state_callback(outgoing->dial, pbx_outgoing_state_callback);
 	}
 
-	if (channel) {
-		*channel = dialed;
-		ast_channel_ref(*channel);
-		ast_channel_lock(*channel);
-	}
-
-	ast_mutex_init(&outgoing->lock);
-	ast_cond_init(&outgoing->cond, NULL);
+	if (locked_channel) {
+		/*
+		 * Keep a dialed channel ref since the caller wants
+		 * the channel returned.  We must get the ref before
+		 * spawning off pbx_outgoing_exec().
+		 */
+		ast_channel_ref(dialed);
+		if (!synchronous) {
+			/*
+			 * Lock it now to hold off pbx_outgoing_exec() in case the
+			 * calling function needs the channel state/snapshot before
+			 * dialing actually happens.
+			 */
+			ast_channel_lock(dialed);
+		}
+	}
 
 	ao2_ref(outgoing, +1);
-
-	ast_mutex_lock(&outgoing->lock);
-
 	if (ast_pthread_create_detached(&thread, NULL, pbx_outgoing_exec, outgoing)) {
 		ast_log(LOG_WARNING, "Unable to spawn dialing thread for '%s/%s'\n", type, addr);
-		if (channel) {
-			ast_channel_unlock(*channel);
-			ast_channel_unref(*channel);
-		}
-		ast_mutex_unlock(&outgoing->lock);
 		ao2_ref(outgoing, -1);
+		if (locked_channel) {
+			if (!synchronous) {
+				ast_channel_unlock(dialed);
+			}
+			ast_channel_unref(dialed);
+		}
 		return -1;
 	}
 
-	/* Wait for dialing to complete */
 	if (synchronous) {
-		if (channel && *channel) {
-			ast_channel_unlock(*channel);
-		}
+		ao2_lock(outgoing);
+		/* Wait for dialing to complete */
 		while (!outgoing->dialed) {
-			ast_cond_wait(&outgoing->cond, &outgoing->lock);
-
-			if (outgoing->dial_res != AST_DIAL_RESULT_ANSWERED) {
-				ast_mutex_unlock(&outgoing->lock);
-				/* The dial operation failed. */
-				return -1;
-			}
-		}
-		if (channel && *channel) {
-			ast_channel_lock(*channel);
-		}
-	}
-
-	/* Wait for execution to complete */
-	if (synchronous > 1) {
-		while (!outgoing->executed) {
-			ast_cond_wait(&outgoing->cond, &outgoing->lock);
-		}
-	}
-
-	ast_mutex_unlock(&outgoing->lock);
-
-	if (reason) {
-		*reason = ast_dial_reason(outgoing->dial, 0);
-	}
-
-	if ((synchronous > 1) && ast_dial_state(outgoing->dial) != AST_DIAL_RESULT_ANSWERED &&
-		ast_strlen_zero(app) &&	ast_exists_extension(NULL, context, "failed", 1, NULL)) {
-		struct ast_channel *failed = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, NULL, 0, "OutgoingSpoolFailed");
-
+			ast_cond_wait(&outgoing->cond, ao2_object_get_lockaddr(outgoing));
+		}
+		if (1 < synchronous
+			&& outgoing->dial_res == AST_DIAL_RESULT_ANSWERED) {
+			/* Wait for execution to complete */
+			while (!outgoing->executed) {
+				ast_cond_wait(&outgoing->cond, ao2_object_get_lockaddr(outgoing));
+			}
+		}
+		ao2_unlock(outgoing);
+
+		/* Determine the outcome of the dialing attempt up to it being answered. */
+		if (reason) {
+			*reason = pbx_dial_reason(outgoing->dial_res,
+				ast_dial_reason(outgoing->dial, 0));
+		}
+
+		if (outgoing->dial_res != AST_DIAL_RESULT_ANSWERED) {
+			/* The dial operation failed. */
+			if (locked_channel) {
+				ast_channel_unref(dialed);
+			}
+			return -1;
+		}
+		if (locked_channel) {
+			ast_channel_lock(dialed);
+		}
+	}
+
+	if (locked_channel) {
+		*locked_channel = dialed;
+	}
+	return 0;
+}
+
+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 **locked_channel, int early_media,
+	const struct ast_assigned_ids *assignedids)
+{
+	int res;
+	int my_reason;
+
+	if (!reason) {
+		reason = &my_reason;
+	}
+	*reason = 0;
+	if (locked_channel) {
+		*locked_channel = NULL;
+	}
+
+	res = pbx_outgoing_attempt(type, cap, addr, timeout, context, exten, priority,
+		NULL, NULL, reason, synchronous, cid_num, cid_name, vars, account, locked_channel,
+		early_media, assignedids);
+
+	if (res < 0 /* Call failed to get connected for some reason. */
+		&& 1 < synchronous
+		&& ast_exists_extension(NULL, context, "failed", 1, NULL)) {
+		struct ast_channel *failed;
+
+		/* We do not have to worry about a locked_channel if dialing failed. */
+		ast_assert(!locked_channel || !*locked_channel);
+
+		/*!
+		 * \todo XXX Not good.  The channel name is not unique if more than
+		 * one originate fails at a time.
+		 */
+		failed = ast_channel_alloc(0, AST_STATE_DOWN, cid_num, cid_name, account,
+			"failed", context, NULL, NULL, 0, "OutgoingSpoolFailed");
 		if (failed) {
-			char failed_reason[4] = "";
-
-			if (!ast_strlen_zero(context)) {
-				ast_channel_context_set(failed, context);
-			}
-
-			if (account) {
-				ast_channel_accountcode_set(failed, account);
-			}
-
-			set_ext_pri(failed, "failed", 1);
+			char failed_reason[12];
+
 			ast_set_variables(failed, vars);
-			snprintf(failed_reason, sizeof(failed_reason), "%d", ast_dial_reason(outgoing->dial, 0));
+			snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
 			pbx_builtin_setvar_helper(failed, "REASON", failed_reason);
 			ast_channel_unlock(failed);
 
 			if (ast_pbx_run(failed)) {
-				ast_log(LOG_ERROR, "Unable to run PBX on '%s'\n", ast_channel_name(failed));
+				ast_log(LOG_ERROR, "Unable to run PBX on '%s'\n",
+					ast_channel_name(failed));
 				ast_hangup(failed);
 			}
 		}
 	}
 
-	return 0;
-}
-
-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, const struct ast_assigned_ids *assignedids)
-{
-	return pbx_outgoing_attempt(type, cap, addr, timeout, context, exten, priority, NULL, NULL, reason, synchronous, cid_num,
-		cid_name, vars, account, channel, early_media, assignedids);
-}
-
-int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, const struct ast_assigned_ids *assignedids)
-{
+	return res;
+}
+
+int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr,
+	int timeout, const char *app, const char *appdata, int *reason, int synchronous,
+	const char *cid_num, const char *cid_name, struct ast_variable *vars,
+	const char *account, struct ast_channel **locked_channel,
+	const struct ast_assigned_ids *assignedids)
+{
+	if (reason) {
+		*reason = 0;
+	}
+	if (locked_channel) {
+		*locked_channel = NULL;
+	}
 	if (ast_strlen_zero(app)) {
 		return -1;
 	}
 
-	return pbx_outgoing_attempt(type, cap, addr, timeout, NULL, NULL, 0, app, appdata, reason, synchronous, cid_num,
-		cid_name, vars, account, locked_channel, 0, assignedids);
+	return pbx_outgoing_attempt(type, cap, addr, timeout, NULL, NULL, 0, app, appdata,
+		reason, synchronous, cid_num, cid_name, vars, account, locked_channel, 0,
+		assignedids);
 }
 
 /* this is the guts of destroying a context --




More information about the asterisk-commits mailing list