[asterisk-commits] dvossel: branch dvossel/generic_aoc r256484 - /team/dvossel/generic_aoc/chann...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Apr 8 18:13:55 CDT 2010


Author: dvossel
Date: Thu Apr  8 18:13:54 2010
New Revision: 256484

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=256484
Log:
guarantees AOC-E messages received on pri disconnect are read off ast_channel before hangup

Modified:
    team/dvossel/generic_aoc/channels/sig_pri.c

Modified: team/dvossel/generic_aoc/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/generic_aoc/channels/sig_pri.c?view=diff&rev=256484&r1=256483&r2=256484
==============================================================================
--- team/dvossel/generic_aoc/channels/sig_pri.c (original)
+++ team/dvossel/generic_aoc/channels/sig_pri.c Thu Apr  8 18:13:54 2010
@@ -2362,7 +2362,6 @@
  */
 static void sig_pri_aoc_e_from_pri(const struct pri_subcmd_aoc_e *aoc_e, struct ast_channel *owner)
 {
-
 	struct ast_aoc_decoded *decoded = NULL;
 	struct ast_aoc_encoded *encoded = NULL;
 	size_t encoded_size = 0;
@@ -2958,6 +2957,45 @@
 		}
 	}
 }
+
+
+#if defined(HAVE_PRI_AOC_EVENTS)
+/*!
+ * \internal
+ * \brief detect if AOC-S subcmd is present.
+ * \since 1.8
+ *
+ * \param subcmds Subcommands to process if any. (Could be NULL).
+ *
+ * \note Knowing whether or not an AOC-E subcmd is present on certain
+ * PRI hangup events is necessary to determine what method to use to hangup
+ * the ast_channel.  If an AOC-E subcmd just came in, then a new AOC-E was queued
+ * on the ast_channel.  If a soft hangup is used, the AOC-E msg will never make it
+ * across the bridge, but if a AST_CONTROL_HANGUP frame is queued behind it
+ * we can ensure the AOC-E frame makes it to it's destination before the hangup
+ * frame is read.
+ *
+ *
+ * \retval 0 AOC-E is not present in subcmd list
+ * \retval 1 AOC-E is present in subcmd list
+ */
+static int detect_aoc_e_subcmd(const struct pri_subcommands *subcmds)
+{
+	int i;
+
+	if (!subcmds) {
+		return 0;
+	}
+	for (i = 0; i < subcmds->counter_subcmd; ++i) {
+		const struct pri_subcommand *subcmd = &subcmds->subcmd[i];
+		if (subcmd->cmd == PRI_SUBCMD_AOC_E) {
+			return 1;
+		}
+	}
+	return 0;
+}
+#endif	/* defined(HAVE_PRI_AOC_EVENTS) */
+
 
 /*!
  * \internal
@@ -4492,12 +4530,13 @@
 								break;
 							}
 							if (pri->pvts[chanpos]->owner) {
+								int do_hangup = 0;
 								/* Queue a BUSY instead of a hangup if our cause is appropriate */
 								pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
 								switch (pri->pvts[chanpos]->owner->_state) {
 								case AST_STATE_BUSY:
 								case AST_STATE_UP:
-									ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
+									do_hangup = 1;
 									break;
 								default:
 									switch (e->hangup.cause) {
@@ -4513,10 +4552,24 @@
 										pri_queue_control(pri->pvts[chanpos], AST_CONTROL_CONGESTION, pri);
 										break;
 									default:
-										ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
+										do_hangup = 1;
 										break;
 									}
 									break;
+								}
+
+								if (do_hangup) {
+#if defined(HAVE_PRI_AOC_EVENTS)
+									if (detect_aoc_e_subcmd(e->hangup.subcmds)) {
+										/* If a AOC-E msg was sent during the Disconnect, we must use a
+										 * AST_CONTROL_HANGUP frame to guarantee that frame gets read before hangup */
+										ast_queue_control(pri->pvts[chanpos]->owner, AST_CONTROL_HANGUP);
+									} else {
+										ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
+									}
+#else
+									ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
+#endif
 								}
 							}
 							ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
@@ -4595,11 +4648,13 @@
 							break;
 						}
 						if (pri->pvts[chanpos]->owner) {
+							int do_hangup = 0;
+
 							pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
 							switch (pri->pvts[chanpos]->owner->_state) {
 							case AST_STATE_BUSY:
 							case AST_STATE_UP:
-								ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
+								do_hangup = 1;
 								break;
 							default:
 								switch (e->hangup.cause) {
@@ -4615,15 +4670,27 @@
 									pri_queue_control(pri->pvts[chanpos], AST_CONTROL_CONGESTION, pri);
 									break;
 								default:
-									ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
+									do_hangup = 1;
 									break;
 								}
 								break;
 							}
-							ast_verb(3, "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
-							if (e->hangup.aoc_units > -1)
-								ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
-									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
+
+							if (do_hangup) {
+#if defined(HAVE_PRI_AOC_EVENTS)
+								if (detect_aoc_e_subcmd(e->hangup.subcmds)) {
+									/* If a AOC-E msg was sent during the Disconnect, we must use a AST_CONTROL_HANGUP frame
+									 * to guarantee that frame gets read before hangup */
+									ast_queue_control(pri->pvts[chanpos]->owner, AST_CONTROL_HANGUP);
+								} else {
+									ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
+								}
+#else
+								ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
+#endif
+							}
+							ast_verb(3, "Channel %d/%d, span %d got hangup request, cause %d\n",
+								PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
 						} else {
 							pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
 							pri->pvts[chanpos]->call = NULL;




More information about the asterisk-commits mailing list