summaryrefslogtreecommitdiff
path: root/channels/sig_pri.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2015-04-20 18:00:34 -0500
committerRichard Mudgett <rmudgett@digium.com>2015-04-20 19:07:57 -0500
commit614f5066905fa5efb7cfce9dfa397640808c4dd2 (patch)
tree2331f7adac0ae4c9cf6ab383e390df18b9308c1f /channels/sig_pri.c
parentb1deedf0dc25537bd6a714f075f609e4261a4f0f (diff)
chan_dahdi/sig_pri: Make post AMI HangupRequest events on PRI channels.
The chan_dahdi channel driver is a very old driver. The ability for it to support ISDN was added well after the initial analog support. Setting the softhangup flags is a carry over from the original analog code. The driver was not updated to call ast_queue_hangup() which will post the AMI HangupRequest event. * Changed sig_pri.c to call ast_queue_hangup() instead of setting the softhangup flag when the remote party initiates a hangup. ASTERISK-24895 #close Reported by: Andrew Zherdin Change-Id: I5fe2e48556507785fd8ab8e1c960683fd5d20325
Diffstat (limited to 'channels/sig_pri.c')
-rw-r--r--channels/sig_pri.c113
1 files changed, 43 insertions, 70 deletions
diff --git a/channels/sig_pri.c b/channels/sig_pri.c
index a7cc3d7a7..e4ad589c1 100644
--- a/channels/sig_pri.c
+++ b/channels/sig_pri.c
@@ -1376,10 +1376,9 @@ static void sig_pri_queue_unhold(struct sig_pri_span *pri, int chanpos)
static void pri_queue_control(struct sig_pri_span *pri, int chanpos, int subclass)
{
struct ast_frame f = {AST_FRAME_CONTROL, };
- struct sig_pri_chan *p = pri->pvts[chanpos];
if (sig_pri_callbacks.queue_control) {
- sig_pri_callbacks.queue_control(p->chan_pvt, subclass);
+ sig_pri_callbacks.queue_control(pri->pvts[chanpos]->chan_pvt, subclass);
}
f.subclass.integer = subclass;
@@ -1388,6 +1387,31 @@ static void pri_queue_control(struct sig_pri_span *pri, int chanpos, int subclas
/*!
* \internal
+ * \brief Queue a request to hangup control frame onto the owner channel.
+ *
+ * \param pri PRI span control structure.
+ * \param chanpos Channel position in the span.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
+ *
+ * \return Nothing
+ */
+static void sig_pri_queue_hangup(struct sig_pri_span *pri, int chanpos)
+{
+ if (sig_pri_callbacks.queue_control) {
+ sig_pri_callbacks.queue_control(pri->pvts[chanpos]->chan_pvt, AST_CONTROL_HANGUP);
+ }
+
+ sig_pri_lock_owner(pri, chanpos);
+ if (pri->pvts[chanpos]->owner) {
+ ast_queue_hangup(pri->pvts[chanpos]->owner);
+ ast_channel_unlock(pri->pvts[chanpos]->owner);
+ }
+}
+
+/*!
+ * \internal
* \brief Queue a PVT_CAUSE_CODE frame onto the owner channel.
* \since 11
*
@@ -4035,14 +4059,14 @@ static void sig_pri_send_aoce_termination_request(struct sig_pri_span *pri, int
}
if (!(decoded = ast_aoc_create(AST_AOC_REQUEST, 0, AST_AOC_REQUEST_E))) {
- ast_softhangup_nolock(pvt->owner, AST_SOFTHANGUP_DEV);
+ ast_queue_hangup(pvt->owner);
goto cleanup_termination_request;
}
ast_aoc_set_termination_request(decoded);
if (!(encoded = ast_aoc_encode(decoded, &encoded_size, pvt->owner))) {
- ast_softhangup_nolock(pvt->owner, AST_SOFTHANGUP_DEV);
+ ast_queue_hangup(pvt->owner);
goto cleanup_termination_request;
}
@@ -4051,7 +4075,7 @@ static void sig_pri_send_aoce_termination_request(struct sig_pri_span *pri, int
whentohangup.tv_sec = ms / 1000;
if (ast_queue_control_data(pvt->owner, AST_CONTROL_AOC, encoded, encoded_size)) {
- ast_softhangup_nolock(pvt->owner, AST_SOFTHANGUP_DEV);
+ ast_queue_hangup(pvt->owner);
goto cleanup_termination_request;
}
@@ -4295,43 +4319,6 @@ static void sig_pri_handle_cis_subcmds(struct sig_pri_span *pri, int event_id,
}
}
-#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
* \brief Handle the call associated PRI subcommand events.
@@ -6567,9 +6554,8 @@ static void *pri_dchannel(void *vpri)
pri->pvts[chanpos]->call = NULL;
}
}
- /* Force soft hangup if appropriate */
- if (pri->pvts[chanpos]->owner)
- ast_channel_softhangup_internal_flag_add(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
+ /* Force hangup if appropriate */
+ sig_pri_queue_hangup(pri, chanpos);
sig_pri_unlock_private(pri->pvts[chanpos]);
}
} else {
@@ -6581,8 +6567,8 @@ static void *pri_dchannel(void *vpri)
pri_destroycall(pri->pri, pri->pvts[x]->call);
pri->pvts[x]->call = NULL;
}
- if (pri->pvts[x]->owner)
- ast_channel_softhangup_internal_flag_add(pri->pvts[x]->owner, AST_SOFTHANGUP_DEV);
+ /* Force hangup if appropriate */
+ sig_pri_queue_hangup(pri, x);
sig_pri_unlock_private(pri->pvts[x]);
}
}
@@ -7154,17 +7140,7 @@ static void *pri_dchannel(void *vpri)
}
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 release, we must use a
- * AST_CONTROL_HANGUP frame to guarantee that frame gets read before hangup */
- pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
- } else {
- ast_channel_softhangup_internal_flag_add(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
- }
-#else
- ast_channel_softhangup_internal_flag_add(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
-#endif /* defined(HAVE_PRI_AOC_EVENTS) */
+ sig_pri_queue_hangup(pri, chanpos);
}
} else {
/*
@@ -7314,16 +7290,11 @@ static void *pri_dchannel(void *vpri)
&& ast_channel_is_bridged(pri->pvts[chanpos]->owner)) {
sig_pri_send_aoce_termination_request(pri, chanpos,
pri_get_timer(pri->pri, PRI_TIMER_T305) / 2);
- } else 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 */
- pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
- } else {
- ast_channel_softhangup_internal_flag_add(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
- }
-#else
- ast_channel_softhangup_internal_flag_add(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
+ } else
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
+ {
+ sig_pri_queue_hangup(pri, chanpos);
+ }
}
ast_verb(3, "Span %d: Channel %d/%d got hangup request, cause %d\n",
pri->span, pri->pvts[chanpos]->logicalspan,
@@ -8619,16 +8590,18 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi
if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E) {
sig_pri_aoc_e_from_ast(p, decoded);
}
- /* if hangup was delayed for this AOC-E msg, waiting_for_aoc
+ /*
+ * If hangup was delayed for this AOC-E msg, waiting_for_aoc
* will be set. A hangup is already occuring via a timeout during
* this delay. Instead of waiting for that timeout to occur, go ahead
- * and initiate the softhangup since the delay is no longer necessary */
+ * and initiate the hangup since the delay is no longer necessary.
+ */
if (p->waiting_for_aoce) {
p->waiting_for_aoce = 0;
ast_debug(1,
"Received final AOC-E msg, continue with hangup on %s\n",
ast_channel_name(chan));
- ast_softhangup_nolock(chan, AST_SOFTHANGUP_DEV);
+ ast_queue_hangup(chan);
}
break;
case AST_AOC_REQUEST: