diff --git a/libpri.h b/libpri.h index afbb029..89dbb2a 100644 --- a/libpri.h +++ b/libpri.h @@ -915,6 +915,17 @@ int pri_redirecting_update(struct pri *pri, q931_call *call, const struct pri_pa #define PRI_HANGUP int pri_hangup(struct pri *pri, q931_call *call, int cause); +/*! + * \brief Set the call hangup fix enable flag. + * + * \param ctrl D channel controller. + * \param enable TRUE to follow Q.931 Section 5.3.2 call hangup better. + * FALSE for legacy behaviour. (Default FALSE if not called.) + * + * \return Nothing + */ +void pri_hangup_fix_enable(struct pri *ctrl, int enable); + #define PRI_DESTROYCALL void pri_destroycall(struct pri *pri, q931_call *call); diff --git a/pri.c b/pri.c index 80a7b2b..4aa9456 100644 --- a/pri.c +++ b/pri.c @@ -965,6 +965,14 @@ int pri_channel_bridge(q931_call *call1, q931_call *call2) } } +void pri_hangup_fix_enable(struct pri *ctrl, int enable) +{ + if (ctrl) { + ctrl = PRI_MASTER(ctrl); + ctrl->hangup_fix_enabled = enable ? 1 : 0; + } +} + int pri_hangup(struct pri *pri, q931_call *call, int cause) { if (!pri || !call) diff --git a/pri_internal.h b/pri_internal.h index eb49577..edb8bb6 100644 --- a/pri_internal.h +++ b/pri_internal.h @@ -92,6 +92,7 @@ struct pri { unsigned int service_message_support:1;/* TRUE if upper layer supports SERVICE messages */ unsigned int hold_support:1;/* TRUE if upper layer supports call hold. */ unsigned int deflection_support:1;/* TRUE if upper layer supports call deflection/rerouting. */ + unsigned int hangup_fix_enabled:1;/* TRUE if should follow Q.931 Section 5.3.2 instead of blindly sending RELEASE_COMPLETE for certain causes */ /* MDL variables */ int mdl_error; diff --git a/q931.c b/q931.c index d1b0325..867e373 100644 --- a/q931.c +++ b/q931.c @@ -5397,6 +5397,12 @@ static int __q931_hangup(struct pri *ctrl, q931_call *c, int cause) case PRI_CAUSE_REQUESTED_CHAN_UNAVAIL: case PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST: case PRI_CAUSE_UNALLOCATED: + if (!PRI_MASTER(ctrl)->hangup_fix_enabled) { + /* Legacy: We'll send RELEASE_COMPLETE with these causes */ + disconnect = 0; + release_compl = 1; + break; + } /* See Q.931 Section 5.3.2 a) */ switch (c->ourcallstate) { case Q931_CALL_STATE_NULL: