diff --git a/doc/cc_ptmp_agent.fsm b/doc/cc_ptmp_agent.fsm index d298596..e28fd3c 100644 --- a/doc/cc_ptmp_agent.fsm +++ b/doc/cc_ptmp_agent.fsm @@ -25,7 +25,13 @@ FSM CC_PTMP_Agent Action Send_CC_Available(Q931_DISCONNECT); Next_State CC_STATE_AVAILABLE; } + Stimulus CC_EVENT_INTERNAL_CLEARING { + Action Release_LinkID; + Action Pass_Up_CC_Cancel; + Next_State CC_STATE_IDLE; + } Stimulus CC_EVENT_CANCEL { + Action Release_LinkID; Next_State CC_STATE_IDLE; } } @@ -45,6 +51,10 @@ FSM CC_PTMP_Agent Action Pass_Up_CC_Request; Next_State CC_STATE_REQUESTED; } + Stimulus CC_EVENT_INTERNAL_CLEARING { + Action Stop_T_RETENTION; + Action Start_T_RETENTION; + } Stimulus CC_EVENT_TIMEOUT_T_RETENTION { Action Send_EraseCallLinkageID; Action Release_LinkID; diff --git a/doc/cc_ptmp_agent_flattened.fsm b/doc/cc_ptmp_agent_flattened.fsm index e454e3d..0b4f3e2 100644 --- a/doc/cc_ptmp_agent_flattened.fsm +++ b/doc/cc_ptmp_agent_flattened.fsm @@ -20,7 +20,14 @@ FSM CC_PTMP_Agent Action Send_CC_Available(Q931_DISCONNECT); Next_State CC_STATE_AVAILABLE; } + Stimulus CC_EVENT_INTERNAL_CLEARING { + Action Release_LinkID; + Action Pass_Up_CC_Cancel; + Action Set_Selfdestruct; + Next_State CC_STATE_IDLE; + } Stimulus CC_EVENT_CANCEL { + Action Release_LinkID; Action Set_Selfdestruct; Next_State CC_STATE_IDLE; } @@ -39,6 +46,10 @@ FSM CC_PTMP_Agent Action Stop_T_RETENTION; Next_State CC_STATE_REQUESTED; } + Stimulus CC_EVENT_INTERNAL_CLEARING { + Action Stop_T_RETENTION; + Action Start_T_RETENTION; + } Stimulus CC_EVENT_TIMEOUT_T_RETENTION { Action Send_EraseCallLinkageID; Action Release_LinkID; diff --git a/doc/cc_ptp_agent.fsm b/doc/cc_ptp_agent.fsm index db02205..3eb8a13 100644 --- a/doc/cc_ptp_agent.fsm +++ b/doc/cc_ptp_agent.fsm @@ -25,6 +25,10 @@ FSM CC_PTP_Agent Action Send_CC_Available(Q931_DISCONNECT); Next_State CC_STATE_AVAILABLE; } + Stimulus CC_EVENT_INTERNAL_CLEARING { + Action Pass_Up_CC_Cancel; + Next_State CC_STATE_IDLE; + } Stimulus CC_EVENT_CANCEL { Next_State CC_STATE_IDLE; } @@ -53,6 +57,10 @@ FSM CC_PTP_Agent Action Stop_T_RETENTION; Next_State CC_STATE_REQUESTED; } + Stimulus CC_EVENT_INTERNAL_CLEARING { + Action Stop_T_RETENTION; + Action Start_T_RETENTION; + } Stimulus CC_EVENT_TIMEOUT_T_RETENTION { Action Pass_Up_CC_Cancel; Next_State CC_STATE_IDLE; diff --git a/doc/cc_ptp_agent_flattened.fsm b/doc/cc_ptp_agent_flattened.fsm index cc48835..5567b5b 100644 --- a/doc/cc_ptp_agent_flattened.fsm +++ b/doc/cc_ptp_agent_flattened.fsm @@ -20,6 +20,11 @@ FSM CC_PTP_Agent Action Send_CC_Available(Q931_DISCONNECT); Next_State CC_STATE_AVAILABLE; } + Stimulus CC_EVENT_INTERNAL_CLEARING { + Action Pass_Up_CC_Cancel; + Action Set_Selfdestruct; + Next_State CC_STATE_IDLE; + } Stimulus CC_EVENT_CANCEL { Action Set_Selfdestruct; Next_State CC_STATE_IDLE; @@ -46,6 +51,10 @@ FSM CC_PTP_Agent Action Stop_T_RETENTION; Next_State CC_STATE_REQUESTED; } + Stimulus CC_EVENT_INTERNAL_CLEARING { + Action Stop_T_RETENTION; + Action Start_T_RETENTION; + } Stimulus CC_EVENT_TIMEOUT_T_RETENTION { Action Pass_Up_CC_Cancel; Action Stop_T_RETENTION; diff --git a/doc/cc_qsig_agent.fsm b/doc/cc_qsig_agent.fsm index f93f8b6..2b2fd79 100644 --- a/doc/cc_qsig_agent.fsm +++ b/doc/cc_qsig_agent.fsm @@ -41,6 +41,10 @@ FSM CC_QSIG_Agent Action Send_Call_Proceeding; Next_State CC_STATE_REQUESTED; } + Stimulus CC_EVENT_INTERNAL_CLEARING { + Action Stop_T_RETENTION; + Action Start_T_RETENTION; + } Stimulus CC_EVENT_TIMEOUT_T_RETENTION { Action Pass_Up_CC_Cancel; Next_State CC_STATE_IDLE; diff --git a/doc/cc_qsig_agent_flattened.fsm b/doc/cc_qsig_agent_flattened.fsm index ceafcd7..e8a5cc0 100644 --- a/doc/cc_qsig_agent_flattened.fsm +++ b/doc/cc_qsig_agent_flattened.fsm @@ -34,6 +34,10 @@ FSM CC_QSIG_Agent Action Stop_T_RETENTION; Next_State CC_STATE_REQUESTED; } + Stimulus CC_EVENT_INTERNAL_CLEARING { + Action Stop_T_RETENTION; + Action Start_T_RETENTION; + } Stimulus CC_EVENT_TIMEOUT_T_RETENTION { Action Pass_Up_CC_Cancel; Action Stop_T_RETENTION; diff --git a/pri_cc.c b/pri_cc.c index b68127b..c939617 100644 --- a/pri_cc.c +++ b/pri_cc.c @@ -2613,6 +2613,9 @@ static const char *pri_cc_fsm_event_str(enum CC_EVENTS event) case CC_EVENT_CANCEL: str = "CC_EVENT_CANCEL"; break; + case CC_EVENT_INTERNAL_CLEARING: + str = "CC_EVENT_INTERNAL_CLEARING"; + break; case CC_EVENT_SIGNALING_GONE: str = "CC_EVENT_SIGNALING_GONE"; break; @@ -4351,7 +4354,14 @@ static void pri_cc_fsm_ptmp_agent_pend_avail(struct pri *ctrl, q931_call *call, pri_cc_act_send_cc_available(ctrl, cc_record, call, Q931_DISCONNECT); cc_record->state = CC_STATE_AVAILABLE; break; + case CC_EVENT_INTERNAL_CLEARING: + pri_cc_act_release_link_id(ctrl, cc_record); + pri_cc_act_pass_up_cc_cancel(ctrl, cc_record); + pri_cc_act_set_self_destruct(ctrl, cc_record); + cc_record->state = CC_STATE_IDLE; + break; case CC_EVENT_CANCEL: + pri_cc_act_release_link_id(ctrl, cc_record); pri_cc_act_set_self_destruct(ctrl, cc_record); cc_record->state = CC_STATE_IDLE; break; @@ -4384,6 +4394,10 @@ static void pri_cc_fsm_ptmp_agent_avail(struct pri *ctrl, q931_call *call, struc pri_cc_act_stop_t_retention(ctrl, cc_record); cc_record->state = CC_STATE_REQUESTED; break; + case CC_EVENT_INTERNAL_CLEARING: + pri_cc_act_stop_t_retention(ctrl, cc_record); + pri_cc_act_start_t_retention(ctrl, cc_record); + break; case CC_EVENT_TIMEOUT_T_RETENTION: pri_cc_act_send_erase_call_linkage_id(ctrl, cc_record); pri_cc_act_release_link_id(ctrl, cc_record); @@ -5275,6 +5289,11 @@ static void pri_cc_fsm_ptp_agent_pend_avail(struct pri *ctrl, q931_call *call, s pri_cc_act_send_cc_available(ctrl, cc_record, call, Q931_DISCONNECT); cc_record->state = CC_STATE_AVAILABLE; break; + case CC_EVENT_INTERNAL_CLEARING: + pri_cc_act_pass_up_cc_cancel(ctrl, cc_record); + pri_cc_act_set_self_destruct(ctrl, cc_record); + cc_record->state = CC_STATE_IDLE; + break; case CC_EVENT_CANCEL: pri_cc_act_set_self_destruct(ctrl, cc_record); cc_record->state = CC_STATE_IDLE; @@ -5315,6 +5334,10 @@ static void pri_cc_fsm_ptp_agent_avail(struct pri *ctrl, q931_call *call, struct pri_cc_act_stop_t_retention(ctrl, cc_record); cc_record->state = CC_STATE_REQUESTED; break; + case CC_EVENT_INTERNAL_CLEARING: + pri_cc_act_stop_t_retention(ctrl, cc_record); + pri_cc_act_start_t_retention(ctrl, cc_record); + break; case CC_EVENT_TIMEOUT_T_RETENTION: pri_cc_act_pass_up_cc_cancel(ctrl, cc_record); pri_cc_act_stop_t_retention(ctrl, cc_record); @@ -5914,6 +5937,10 @@ static void pri_cc_fsm_qsig_agent_avail(struct pri *ctrl, q931_call *call, struc pri_cc_act_stop_t_retention(ctrl, cc_record); cc_record->state = CC_STATE_REQUESTED; break; + case CC_EVENT_INTERNAL_CLEARING: + pri_cc_act_stop_t_retention(ctrl, cc_record); + pri_cc_act_start_t_retention(ctrl, cc_record); + break; case CC_EVENT_TIMEOUT_T_RETENTION: pri_cc_act_pass_up_cc_cancel(ctrl, cc_record); pri_cc_act_stop_t_retention(ctrl, cc_record); diff --git a/pri_internal.h b/pri_internal.h index 8235092..bf0ffb7 100644 --- a/pri_internal.h +++ b/pri_internal.h @@ -664,6 +664,8 @@ enum CC_EVENTS { CC_EVENT_LINK_CANCEL, /*! Tear down CC request from upper layer. */ CC_EVENT_CANCEL, + /*! Abnormal clearing of original call. (T309 processing/T309 timeout/TEI removal) */ + CC_EVENT_INTERNAL_CLEARING, /*! Received message indicating tear down of CC signaling link completed. */ CC_EVENT_SIGNALING_GONE, /*! Delayed hangup request for the signaling link to allow subcmd events to be passed up. */ diff --git a/q931.c b/q931.c index 764dfd8..8d06310 100644 --- a/q931.c +++ b/q931.c @@ -8472,22 +8472,31 @@ static int pri_internal_clear(void *data) pri_message(ctrl, "clearing, alive %d, hangupack %d\n", c->alive, c->sendhangupack); } - if (c->cc.record && c->cc.record->signaling == c) { - pri_cc_event(ctrl, c, c->cc.record, CC_EVENT_SIGNALING_GONE); + if (c->cc.record) { + if (c->cc.record->signaling == c) { + pri_cc_event(ctrl, c, c->cc.record, CC_EVENT_SIGNALING_GONE); + } else if (c->cc.record->original_call == c) { + pri_cc_event(ctrl, c, c->cc.record, CC_EVENT_INTERNAL_CLEARING); + } } /* Free resources */ if (c->alive) { + c->alive = 0; ctrl->ev.e = PRI_EVENT_HANGUP; res = Q931_RES_HAVEEVENT; - c->alive = 0; } else if (c->sendhangupack) { - res = Q931_RES_HAVEEVENT; - ctrl->ev.e = PRI_EVENT_HANGUP_ACK; pri_hangup(ctrl, c, c->cause); + ctrl->ev.e = PRI_EVENT_HANGUP_ACK; + res = Q931_RES_HAVEEVENT; } else { - res = 0; pri_hangup(ctrl, c, c->cause); + if (ctrl->subcmds.counter_subcmd) { + q931_fill_facility_event(ctrl, ctrl->link.dummy_call); + res = Q931_RES_HAVEEVENT; + } else { + res = 0; + } } return res;