diff options
author | Richard Mudgett <rmudgett@digium.com> | 2015-04-20 18:00:34 -0500 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2015-04-20 19:06:48 -0500 |
commit | d08446ec36600348090eb2451c5a9a7aadd633de (patch) | |
tree | 32c5777b858f2c2f915d040c2a2e09bb35022a54 /channels | |
parent | 96e18453f4e14612737c84301fc442ffc53eec46 (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')
-rw-r--r-- | channels/sig_pri.c | 113 |
1 files changed, 43 insertions, 70 deletions
diff --git a/channels/sig_pri.c b/channels/sig_pri.c index 37d3e49c7..395ae354c 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 * @@ -4037,14 +4061,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; } @@ -4053,7 +4077,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; } @@ -4297,43 +4321,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. @@ -6579,9 +6566,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 { @@ -6593,8 +6579,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]); } } @@ -7166,17 +7152,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 { /* @@ -7326,16 +7302,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, @@ -8632,16 +8603,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: |