[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