[svn-commits] rmudgett: branch rmudgett/dahdi_deflection r223051 - /team/rmudgett/dahdi_def...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Oct 8 19:26:26 CDT 2009


Author: rmudgett
Date: Thu Oct  8 19:26:22 2009
New Revision: 223051

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=223051
Log:
Initial call deflection/rerouting support.

Modified:
    team/rmudgett/dahdi_deflection/channels/sig_pri.c
    team/rmudgett/dahdi_deflection/channels/sig_pri.h

Modified: team/rmudgett/dahdi_deflection/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/dahdi_deflection/channels/sig_pri.c?view=diff&rev=223051&r1=223050&r2=223051
==============================================================================
--- team/rmudgett/dahdi_deflection/channels/sig_pri.c (original)
+++ team/rmudgett/dahdi_deflection/channels/sig_pri.c Thu Oct  8 19:26:22 2009
@@ -1144,6 +1144,68 @@
 
 /*!
  * \internal
+ * \brief Convert libpri redirecting information into asterisk redirecting information.
+ * \since 1.6.4
+ *
+ * \param ast_redirecting Asterisk redirecting structure to fill.
+ * \param pri_redirecting libpri redirecting structure containing source information.
+ * \param ast_guide Asterisk redirecting structure to use as an initialization guide.
+ * \param pri Span controlling structure.
+ * \param from_number Scratch buffer to hold converted from number.
+ * \param to_number Scratch buffer to hold converted to number.
+ * \param number_buf_size Size of the scratch buffers.
+ *
+ * \return Nothing
+ */
+static void sig_pri_redirecting_convert(struct ast_party_redirecting *ast_redirecting,
+	const struct pri_party_redirecting *pri_redirecting,
+	const struct ast_party_redirecting *ast_guide,
+	struct sig_pri_pri *pri,
+	char *from_number,
+	char *to_number,
+	size_t number_buf_size)
+{
+	ast_party_redirecting_set_init(ast_redirecting, ast_guide);
+
+	/* ast_redirecting->from */
+	if (pri_redirecting->from.name.valid) {
+		ast_redirecting->from.name = (char *) pri_redirecting->from.name.str;
+	}
+	if (pri_redirecting->from.number.valid) {
+		apply_plan_to_number(from_number, number_buf_size, pri,
+			pri_redirecting->from.number.str,
+			pri_redirecting->from.number.plan);
+		ast_redirecting->from.number = from_number;
+		ast_redirecting->from.number_type = pri_redirecting->from.number.plan;
+	}
+	if (pri_redirecting->from.name.valid
+		|| pri_redirecting->from.number.valid) {
+		ast_redirecting->from.number_presentation =
+			overall_ast_presentation(&pri_redirecting->from);
+	}
+
+	/* ast_redirecting->to */
+	if (pri_redirecting->to.name.valid) {
+		ast_redirecting->to.name = (char *) pri_redirecting->to.name.str;
+	}
+	if (pri_redirecting->to.number.valid) {
+		apply_plan_to_number(to_number, number_buf_size, pri,
+			pri_redirecting->to.number.str, pri_redirecting->to.number.plan);
+		ast_redirecting->to.number = to_number;
+		ast_redirecting->to.number_type = pri_redirecting->to.number.plan;
+	}
+	if (pri_redirecting->to.name.valid
+		|| pri_redirecting->to.number.valid) {
+		ast_redirecting->to.number_presentation =
+			overall_ast_presentation(&pri_redirecting->from);
+	}
+
+	ast_redirecting->count = pri_redirecting->count;
+	ast_redirecting->reason = pri_to_ast_reason(pri_redirecting->reason);
+}
+
+/*!
+ * \internal
  * \brief Determine if the given extension matches one of the MSNs in the pattern list.
  * \since 1.6.3
  *
@@ -1216,6 +1278,10 @@
  * \param event_id PRI event id
  * \param channel PRI encoded span/channel
  * \param subcmds Subcommands to process if any. (Could be NULL).
+ * \param call_rsp libpri opaque call structure to send any responses toward.
+ * Could be NULL either because it is not available or the call is for the
+ * dummy call reference.  However, this should not be NULL in the cases that
+ * need to use the pointer to send a response message back.
  *
  * \note Assumes the pri->lock is already obtained.
  * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
@@ -1223,10 +1289,13 @@
  * \return Nothing
  */
 static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int event_id,
-	int channel, const struct pri_subcommands *subcmds)
+	int channel, const struct pri_subcommands *subcmds, q931_call *call_rsp)
 {
 	int index;
 	struct ast_channel *owner;
+	struct ast_party_redirecting ast_redirecting;
+	char from_number[AST_MAX_EXTENSION];
+	char to_number[AST_MAX_EXTENSION];
 
 	if (!subcmds) {
 		return;
@@ -1302,50 +1371,9 @@
 			sig_pri_lock_owner(pri, chanpos);
 			owner = pri->pvts[chanpos]->owner;
 			if (owner) {
-				struct ast_party_redirecting ast_redirecting;
-				const struct pri_party_redirecting *pri_redirecting;
-				char from_number[AST_MAX_EXTENSION];
-				char to_number[AST_MAX_EXTENSION];
-
-				ast_party_redirecting_set_init(&ast_redirecting, &owner->redirecting);
-
-				pri_redirecting = &subcmd->u.redirecting;
-
-				/* ast_redirecting.from */
-				if (pri_redirecting->from.name.valid) {
-					ast_redirecting.from.name = (char *) pri_redirecting->from.name.str;
-				}
-				if (pri_redirecting->from.number.valid) {
-					apply_plan_to_number(from_number, sizeof(from_number), pri,
-						pri_redirecting->from.number.str,
-						pri_redirecting->from.number.plan);
-					ast_redirecting.from.number = from_number;
-					ast_redirecting.from.number_type = pri_redirecting->from.number.plan;
-				}
-				if (pri_redirecting->from.name.valid
-					|| pri_redirecting->from.number.valid) {
-					ast_redirecting.from.number_presentation =
-						overall_ast_presentation(&pri_redirecting->from);
-				}
-
-				/* ast_redirecting.to */
-				if (pri_redirecting->to.name.valid) {
-					ast_redirecting.to.name = (char *) pri_redirecting->to.name.str;
-				}
-				if (pri_redirecting->to.number.valid) {
-					apply_plan_to_number(to_number, sizeof(to_number), pri,
-						pri_redirecting->to.number.str, pri_redirecting->to.number.plan);
-					ast_redirecting.to.number = to_number;
-					ast_redirecting.to.number_type = pri_redirecting->to.number.plan;
-				}
-				if (pri_redirecting->to.name.valid
-					|| pri_redirecting->to.number.valid) {
-					ast_redirecting.to.number_presentation =
-						overall_ast_presentation(&pri_redirecting->from);
-				}
-
-				ast_redirecting.count = pri_redirecting->count;
-				ast_redirecting.reason = pri_to_ast_reason(pri_redirecting->reason);
+				sig_pri_redirecting_convert(&ast_redirecting, &subcmd->u.redirecting,
+					&owner->redirecting, pri, from_number, to_number,
+					sizeof(from_number));
 
 /*! \todo XXX Original called data can be put in a channel data store that is inherited. */
 
@@ -1358,6 +1386,63 @@
 				ast_channel_unlock(owner);
 			}
 			break;
+#if defined(HAVE_PRI_CALL_REROUTING)
+		case PRI_SUBCMD_REROUTING:
+			sig_pri_lock_owner(pri, chanpos);
+			owner = pri->pvts[chanpos]->owner;
+			if (owner) {
+				struct pri_party_redirecting pri_deflection;
+
+				if (!call_rsp) {
+					ast_channel_unlock(owner);
+					ast_log(LOG_WARNING,
+						"CallRerouting/CallDeflection to '%s' without call!\n",
+						subcmd->u.rerouting.deflection.to.number.str);
+					break;
+				}
+
+				pri_deflection = subcmd->u.rerouting.deflection;
+
+				ast_string_field_set(owner, call_forward, pri_deflection.to.number.str);
+
+				/* Adjust the deflecting to number based upon the subscription option. */
+				switch (subcmd->u.rerouting.subscription_option) {
+				case 0:	/* noNotification */
+				case 1:	/* notificationWithoutDivertedToNr */
+					/* Delete the number because the far end is not supposed to see it. */
+					pri_deflection.to.number.presentation =
+						PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
+					pri_deflection.to.number.plan =
+						(PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
+					pri_deflection.to.number.str[0] = '\0';
+					break;
+				case 2:	/* notificationWithDivertedToNr */
+					break;
+				case 3:	/* notApplicable */
+				default:
+					break;
+				}
+				sig_pri_redirecting_convert(&ast_redirecting, &pri_deflection,
+					&owner->redirecting, pri, from_number, to_number,
+					sizeof(from_number));
+				ast_channel_set_redirecting(owner, &ast_redirecting);
+
+				/*
+				 * Send back positive ACK to CallRerouting/CallDeflection.
+				 *
+				 * Note:  This call will be hungup by the dial application when
+				 * it processes the call_forward string set above.
+				 */
+				pri_rerouting_rsp(pri->pri, call_rsp, subcmd->u.rerouting.invoke_id,
+					PRI_REROUTING_RSP_OK_CLEAR);
+
+				/* This line is BUSY to further attempts by this dialing attempt. */
+				ast_queue_control(owner, AST_CONTROL_BUSY);
+
+				ast_channel_unlock(owner);
+			}
+			break;
+#endif	/* defined(HAVE_PRI_CALL_REROUTING) */
 		default:
 			ast_debug(2,
 				"Unknown call subcommand(%d) in %s event on channel %d/%d on span %d.\n",
@@ -1493,7 +1578,8 @@
 		retval = -1;
 		goto done_with_owner;
 	}
-	sig_pri_handle_subcmds(pri, chanpos_old, ev->e, ev->hold.channel, ev->hold.subcmds);
+	sig_pri_handle_subcmds(pri, chanpos_old, ev->e, ev->hold.channel, ev->hold.subcmds,
+		ev->hold.call);
 	chanpos_new = pri_fixup_principle(pri, chanpos_new, ev->hold.call);
 	if (chanpos_new < 0) {
 		/* Should never happen. */
@@ -1568,7 +1654,7 @@
 	}
 	sig_pri_lock_private(pri->pvts[chanpos]);
 	sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->retrieve.channel,
-		ev->retrieve.subcmds);
+		ev->retrieve.subcmds, ev->retrieve.call);
 	{
 		struct ast_frame f = { AST_FRAME_CONTROL, };
 
@@ -1906,7 +1992,7 @@
 					if (chanpos > -1) {
 						sig_pri_lock_private(pri->pvts[chanpos]);
 						sig_pri_handle_subcmds(pri, chanpos, e->e, e->digit.channel,
-							e->digit.subcmds);
+							e->digit.subcmds, e->digit.call);
 						/* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
 						if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
 							&& pri->pvts[chanpos]->call == e->digit.call
@@ -1936,7 +2022,7 @@
 					if (chanpos > -1) {
 						sig_pri_lock_private(pri->pvts[chanpos]);
 						sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel,
-							e->ring.subcmds);
+							e->ring.subcmds, e->ring.call);
 						/* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
 						if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
 							&& pri->pvts[chanpos]->call == e->ring.call
@@ -2168,7 +2254,7 @@
 #endif
 
 								sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel,
-									e->ring.subcmds);
+									e->ring.subcmds, e->ring.call);
 							}
 							if (c && !ast_pthread_create_detached(&threadid, NULL, pri_ss_thread, pri->pvts[chanpos])) {
 								ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
@@ -2231,7 +2317,7 @@
 								pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
 
 								sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel,
-									e->ring.subcmds);
+									e->ring.subcmds, e->ring.call);
 							}
 							if (c && !ast_pbx_start(c)) {
 								ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
@@ -2279,7 +2365,7 @@
 						sig_pri_lock_private(pri->pvts[chanpos]);
 
 						sig_pri_handle_subcmds(pri, chanpos, e->e, e->ringing.channel,
-							e->ringing.subcmds);
+							e->ringing.subcmds, e->ringing.call);
 						sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
 						pri_queue_control(pri->pvts[chanpos], AST_CONTROL_RINGING, pri);
 						pri->pvts[chanpos]->alerting = 1;
@@ -2308,7 +2394,7 @@
 				if (chanpos > -1) {
 					sig_pri_lock_private(pri->pvts[chanpos]);
 					sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
-						e->proceeding.subcmds);
+						e->proceeding.subcmds, e->proceeding.call);
 					if ((!pri->pvts[chanpos]->progress)
 #ifdef PRI_PROGRESS_MASK
 						|| (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
@@ -2357,7 +2443,7 @@
 				if (chanpos > -1) {
 					sig_pri_lock_private(pri->pvts[chanpos]);
 					sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
-						e->proceeding.subcmds);
+						e->proceeding.subcmds, e->proceeding.call);
 					if (!pri->pvts[chanpos]->proceeding) {
 						struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
 
@@ -2393,8 +2479,13 @@
 							PRI_SPAN(e->facility.channel), PRI_CHANNEL(e->facility.channel), pri->span);
 					} else {
 						sig_pri_lock_private(pri->pvts[chanpos]);
+#if defined(HAVE_PRI_CALL_REROUTING)
 						sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.channel,
-							e->facility.subcmds);
+							e->facility.subcmds, e->facility.subcall);
+#else
+						sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.channel,
+							e->facility.subcmds, e->facility.call);
+#endif	/* defined(HAVE_PRI_CALL_REROUTING) */
 						sig_pri_unlock_private(pri->pvts[chanpos]);
 					}
 				}
@@ -2413,7 +2504,7 @@
 						sig_pri_lock_private(pri->pvts[chanpos]);
 
 						sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.channel,
-							e->answer.subcmds);
+							e->answer.subcmds, e->answer.call);
 						pri_queue_control(pri->pvts[chanpos], AST_CONTROL_ANSWER, pri);
 						/* Enable echo cancellation if it's not on already */
 						sig_pri_set_dialing(pri->pvts[chanpos], 0);
@@ -2447,7 +2538,7 @@
 					if (chanpos > -1) {
 						sig_pri_lock_private(pri->pvts[chanpos]);
 						sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.channel,
-							e->hangup.subcmds);
+							e->hangup.subcmds, e->hangup.call);
 						if (!pri->pvts[chanpos]->alreadyhungup) {
 							/* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
 							pri->pvts[chanpos]->alreadyhungup = 1;
@@ -2522,7 +2613,7 @@
 					if (chanpos > -1) {
 						sig_pri_lock_private(pri->pvts[chanpos]);
 						sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.channel,
-							e->hangup.subcmds);
+							e->hangup.subcmds, e->hangup.call);
 #if defined(HAVE_PRI_CALL_HOLD)
 						if (e->hangup.call_active && e->hangup.call_held
 							&& pri->hold_disconnect_transfer) {
@@ -2685,7 +2776,7 @@
 					if (chanpos > -1) {
 						sig_pri_lock_private(pri->pvts[chanpos]);
 						sig_pri_handle_subcmds(pri, chanpos, e->e, e->setup_ack.channel,
-							e->setup_ack.subcmds);
+							e->setup_ack.subcmds, e->setup_ack.call);
 						pri->pvts[chanpos]->setup_ack = 1;
 						/* Send any queued digits */
 						for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
@@ -2709,8 +2800,13 @@
 						PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
 				} else {
 					sig_pri_lock_private(pri->pvts[chanpos]);
+#if defined(HAVE_PRI_CALL_HOLD)
 					sig_pri_handle_subcmds(pri, chanpos, e->e, e->notify.channel,
-						e->notify.subcmds);
+						e->notify.subcmds, e->notify.call);
+#else
+					sig_pri_handle_subcmds(pri, chanpos, e->e, e->notify.channel,
+						e->notify.subcmds, NULL);
+#endif	/* !defined(HAVE_PRI_CALL_HOLD) */
 					switch (e->notify.info) {
 					case PRI_NOTIFY_REMOTE_HOLD:
 						if (!pri->discardremoteholdretrieval) {
@@ -3384,6 +3480,9 @@
 #if defined(HAVE_PRI_CALL_HOLD)
 		pri_hold_enable(pri->dchans[i], 1);
 #endif	/* defined(HAVE_PRI_CALL_HOLD) */
+#if defined(HAVE_PRI_CALL_REROUTING)
+		pri_reroute_enable(pri->dchans[i], 1);
+#endif	/* defined(HAVE_PRI_CALL_REROUTING) */
 		/* Enslave to master if appropriate */
 		if (i)
 			pri_enslave(pri->dchans[0], pri->dchans[i]);

Modified: team/rmudgett/dahdi_deflection/channels/sig_pri.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/dahdi_deflection/channels/sig_pri.h?view=diff&rev=223051&r1=223050&r2=223051
==============================================================================
--- team/rmudgett/dahdi_deflection/channels/sig_pri.h (original)
+++ team/rmudgett/dahdi_deflection/channels/sig_pri.h Thu Oct  8 19:26:22 2009
@@ -30,6 +30,7 @@
 #include <libpri.h>
 #include <dahdi/user.h>
 #define HAVE_PRI_CALL_HOLD 1	/* BUGBUG remove this line and put test in configure.ac */
+#define HAVE_PRI_CALL_REROUTING 1	/* BUGBUG remove this line and put test in configure.ac */
 
 enum sig_pri_tone {
 	SIG_PRI_TONE_RINGTONE = 0,




More information about the svn-commits mailing list