[libpri-commits] rmudgett: branch group/ccss r1401 - in /team/group/ccss: ./ doc/
SVN commits to the libpri project
libpri-commits at lists.digium.com
Wed Dec 23 20:01:24 CST 2009
Author: rmudgett
Date: Wed Dec 23 20:01:23 2009
New Revision: 1401
URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1401
Log:
Q.SIG monitor FSM written. Needs testing.
* The Q.SIG signaling link must be retained if the party A number is not
available.
* Added hooks for Q.SIG monitor to determine if it will offer CC to the
upper layer.
Modified:
team/group/ccss/doc/cc_qsig_monitor.fsm
team/group/ccss/doc/cc_qsig_monitor_flattened.fsm
team/group/ccss/pri_cc.c
team/group/ccss/pri_internal.h
team/group/ccss/q931.c
Modified: team/group/ccss/doc/cc_qsig_monitor.fsm
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/doc/cc_qsig_monitor.fsm?view=diff&rev=1401&r1=1400&r2=1401
==============================================================================
--- team/group/ccss/doc/cc_qsig_monitor.fsm (original)
+++ team/group/ccss/doc/cc_qsig_monitor.fsm Wed Dec 23 20:01:23 2009
@@ -152,10 +152,6 @@
}
}
State CC_STATE_ACTIVATED {
- /*
- * The signaling link is not established in this state
- * if retain-signaling-link is false.
- */
Prolog {
Action Reset_A_Status;
}
Modified: team/group/ccss/doc/cc_qsig_monitor_flattened.fsm
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/doc/cc_qsig_monitor_flattened.fsm?view=diff&rev=1401&r1=1400&r2=1401
==============================================================================
--- team/group/ccss/doc/cc_qsig_monitor_flattened.fsm (original)
+++ team/group/ccss/doc/cc_qsig_monitor_flattened.fsm Wed Dec 23 20:01:23 2009
@@ -158,10 +158,6 @@
}
}
State CC_STATE_ACTIVATED {
- /*
- * The signaling link is not established in this state
- * if retain-signaling-link is false.
- */
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Received ccExecPossible */
Action Pass_Up_Remote_User_Free;
Modified: team/group/ccss/pri_cc.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_cc.c?view=diff&rev=1401&r1=1400&r2=1401
==============================================================================
--- team/group/ccss/pri_cc.c (original)
+++ team/group/ccss/pri_cc.c Wed Dec 23 20:01:23 2009
@@ -425,7 +425,6 @@
cc_record->saved_ie_contents = call->cc.saved_ie_contents;
cc_record->bc = call->bc;
cc_record->option.recall_mode = ctrl->cc.option.recall_mode;
-/*! \todo BUGBUG need more initialization?? */
/*
* Append the new record to the end of the list so they are in
@@ -970,16 +969,32 @@
switch (PRI_MASTER(ctrl)->cc.option.signaling_retention_req) {
case 0:/* Want release signaling link. */
+ cc_record->option.retain_signaling_link = 0;
+
msg.args.qsig.CcbsRequest.retain_sig_connection_present = 1;
msg.args.qsig.CcbsRequest.retain_sig_connection = 0;
break;
case 1:/* Demand retain signaling link. */
+ cc_record->option.retain_signaling_link = 1;
+
msg.args.qsig.CcbsRequest.retain_sig_connection_present = 1;
msg.args.qsig.CcbsRequest.retain_sig_connection = 1;
break;
case 2:/* Don't care about signaling link retention. */
default:
- break;
+ cc_record->option.retain_signaling_link = 0;
+ break;
+ }
+ if (!cc_record->party_a.number.valid || cc_record->party_a.number.str[0] == '\0') {
+ /*
+ * Party A number is not available for the other end to initiate
+ * a signaling link to us. We must require that the signaling link
+ * be retained.
+ */
+ cc_record->option.retain_signaling_link = 1;
+
+ msg.args.qsig.CcbsRequest.retain_sig_connection_present = 1;
+ msg.args.qsig.CcbsRequest.retain_sig_connection = 1;
}
pos = rose_encode_invoke(ctrl, pos, end, &msg);
@@ -2280,6 +2295,13 @@
/* The originator does not care. Do how we are configured. */
cc_record->option.retain_signaling_link =
master->cc.option.signaling_retention_rsp;
+ }
+ if (!cc_record->party_a.number.valid || cc_record->party_a.number.str[0] == '\0') {
+ /*
+ * Party A number is not available for us to initiate
+ * a signaling link. We must retain the signaling link.
+ */
+ cc_record->option.retain_signaling_link = 1;
}
/* Link the signaling link to the cc_record. */
@@ -3339,18 +3361,6 @@
response.timeout_time = ctrl->timers[PRI_TIMER_T_ACTIVATE];
break;
case PRI_SWITCH_QSIG:
- switch (PRI_MASTER(ctrl)->cc.option.signaling_retention_req) {
- case 0:/* Want release signaling link. */
- cc_record->option.retain_signaling_link = 0;
- break;
- case 1:/* Demand retain signaling link. */
- cc_record->option.retain_signaling_link = 1;
- break;
- case 2:/* Don't care about signaling link retention. */
- default:
- cc_record->option.retain_signaling_link = 0;
- break;
- }
end = enc_qsig_cc_request(ctrl, buffer, buffer + sizeof(buffer), cc_record);
msgtype = Q931_SETUP;
response.callback = pri_cc_req_response_qsig;
@@ -3520,6 +3530,21 @@
{
PRI_CC_ACT_DEBUG_OUTPUT(ctrl);
cc_record->call_linkage_id = CC_PTMP_INVALID_ID;
+}
+
+/*!
+ * \internal
+ * \brief FSM action to set the Q.SIG retain-signaling-link option.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_record Call completion record to process event.
+ *
+ * \return Nothing
+ */
+static void pri_cc_act_set_retain_signaling_link(struct pri *ctrl, struct pri_cc_record *cc_record)
+{
+ PRI_CC_ACT_DEBUG_OUTPUT(ctrl);
+ cc_record->option.retain_signaling_link = 1;
}
/*!
@@ -5857,6 +5882,449 @@
/*!
* \internal
+ * \brief CC FSM Q.SIG monitor CC_STATE_IDLE.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param cc_record Call completion record to process event.
+ * \param event Event to process.
+ *
+ * \return Nothing
+ */
+static void pri_cc_fsm_qsig_monitor_idle(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
+{
+ switch (event) {
+ case CC_EVENT_AVAILABLE:
+ /*
+ * LibPRI will determine if CC will be offered based upon
+ * if it is even possible.
+ * Essentially:
+ * 1) The call must not have been redirected in this link's
+ * setup.
+ * 2) Received an ALERTING or received a
+ * DISCONNECT(busy/congestion).
+ */
+ pri_cc_act_pass_up_cc_available(ctrl, cc_record);
+ cc_record->state = CC_STATE_AVAILABLE;
+ break;
+ case CC_EVENT_CANCEL:
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ * \internal
+ * \brief CC FSM Q.SIG monitor CC_STATE_AVAILABLE.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param cc_record Call completion record to process event.
+ * \param event Event to process.
+ *
+ * \return Nothing
+ */
+static void pri_cc_fsm_qsig_monitor_avail(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
+{
+ /* The upper layer is responsible for canceling the CC available offering. */
+ switch (event) {
+ case CC_EVENT_CC_REQUEST:
+ /*
+ * Before event is posted:
+ * cc_record->is_ccnr is set.
+ * The signaling connection call record is created.
+ */
+ pri_cc_act_queue_cc_request(ctrl, call, cc_record);
+ /* Start QSIG_CC_T1. */
+ //pri_cc_act_start_t_activate(ctrl, cc_record);
+ cc_record->state = CC_STATE_REQUESTED;
+ break;
+ case CC_EVENT_CANCEL:
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ * \internal
+ * \brief CC FSM Q.SIG monitor CC_STATE_REQUESTED.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param cc_record Call completion record to process event.
+ * \param event Event to process.
+ *
+ * \return Nothing
+ */
+static void pri_cc_fsm_qsig_monitor_req(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
+{
+ switch (event) {
+ case CC_EVENT_CC_REQUEST_ACCEPT:
+ /*
+ * Received ccbsRequest/ccnrRequest response
+ * Before event is posted:
+ * Negotiated CC retention setting saved
+ * Negotiated signaling link retention setting saved
+ */
+ pri_cc_act_stop_t_activate(ctrl, cc_record);
+ if (cc_record->fsm.qsig.msgtype == Q931_RELEASE) {
+ pri_cc_act_disassociate_signaling_link(ctrl, cc_record);
+ if (cc_record->option.retain_signaling_link) {
+ /*
+ * The far end did not honor the
+ * signaling link retention requirement.
+ * ECMA-186 Section 6.5.2.2.1
+ */
+ pri_cc_act_pass_up_cc_req_rsp_timeout(ctrl, cc_record);
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ pri_cc_act_send_cc_cancel(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ }
+ }
+ pri_cc_act_pass_up_cc_req_rsp_success(ctrl, cc_record);
+ /* Start QSIG_CCBS_T2/QSIG_CCNR_T2 depending upon CC mode. */
+ pri_cc_act_start_t_supervision(ctrl, cc_record);
+ pri_cc_act_reset_a_status(ctrl, cc_record);
+ cc_record->state = CC_STATE_ACTIVATED;
+ break;
+ case CC_EVENT_CC_REQUEST_FAIL:
+ pri_cc_act_stop_t_activate(ctrl, cc_record);
+ pri_cc_act_pass_up_cc_req_rsp_fail(ctrl, cc_record);
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ /*
+ * If this request fail comes in with the RELEASE message
+ * then the post action will never get a chance to run.
+ * It will be aborted because the CC_EVENT_SIGNALING_GONE
+ * will be processed first.
+ */
+ pri_cc_act_post_hangup_signaling(ctrl, cc_record);
+ cc_record->state = CC_STATE_WAIT_DESTRUCTION;
+ break;
+ case CC_EVENT_TIMEOUT_T_ACTIVATE:
+ pri_cc_act_stop_t_activate(ctrl, cc_record);
+ pri_cc_act_pass_up_cc_req_rsp_timeout(ctrl, cc_record);
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ pri_cc_act_hangup_signaling_link(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ case CC_EVENT_SIGNALING_GONE:
+ pri_cc_act_stop_t_activate(ctrl, cc_record);
+ /* Claim it was a timeout */
+ pri_cc_act_pass_up_cc_req_rsp_timeout(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:
+ cc_record->state = CC_STATE_WAIT_DESTRUCTION;
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ * \internal
+ * \brief CC FSM Q.SIG monitor CC_STATE_WAIT_DESTRUCTION.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param cc_record Call completion record to process event.
+ * \param event Event to process.
+ *
+ * \return Nothing
+ */
+static void pri_cc_fsm_qsig_monitor_wait_destruction(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
+{
+ /*
+ * Delayed disconnect of the signaling link to allow subcmd events
+ * from the signaling link to be passed up.
+ */
+ switch (event) {
+ case CC_EVENT_CC_REQUEST_ACCEPT:
+ /*
+ * Received ccbsRequest/ccnrRequest response
+ * Before event is posted:
+ * Negotiated CC retention setting saved
+ * Negotiated signaling link retention setting saved
+ */
+ pri_cc_act_stop_t_activate(ctrl, cc_record);
+ if (cc_record->fsm.qsig.msgtype == Q931_RELEASE) {
+ pri_cc_act_disassociate_signaling_link(ctrl, cc_record);
+ }
+ pri_cc_act_send_cc_cancel(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ case CC_EVENT_CC_REQUEST_FAIL:
+ pri_cc_act_stop_t_activate(ctrl, cc_record);
+ /*
+ * If this request fail comes in with the RELEASE message
+ * then the post action will never get a chance to run.
+ * It will be aborted because the CC_EVENT_SIGNALING_GONE
+ * will be processed first.
+ */
+ pri_cc_act_post_hangup_signaling(ctrl, cc_record);
+ break;
+ case CC_EVENT_TIMEOUT_T_ACTIVATE:
+ pri_cc_act_stop_t_activate(ctrl, cc_record);
+ pri_cc_act_hangup_signaling_link(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ case CC_EVENT_SIGNALING_GONE:
+ /* Signaling link cleared. */
+ pri_cc_act_stop_t_activate(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ case CC_EVENT_HANGUP_SIGNALING:
+ //pri_cc_act_stop_t_activate(ctrl, cc_record);
+ pri_cc_act_hangup_signaling_link(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ * \internal
+ * \brief CC FSM Q.SIG monitor CC_STATE_ACTIVATED.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param cc_record Call completion record to process event.
+ * \param event Event to process.
+ *
+ * \return Nothing
+ */
+static void pri_cc_fsm_qsig_monitor_activated(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
+{
+ switch (event) {
+ case CC_EVENT_REMOTE_USER_FREE:
+ /* Received ccExecPossible */
+ pri_cc_act_pass_up_remote_user_free(ctrl, cc_record);
+ /*
+ * ECMA-186 Section 6.5.2.1.7
+ * Implied switch to retain-signaling-link.
+ */
+ pri_cc_act_set_retain_signaling_link(ctrl, cc_record);
+ if (cc_record->fsm.qsig.msgtype == Q931_SETUP) {
+ /* Send Q931_CALL_PROCEEDING message on signaling link. */
+ pri_cc_act_send_call_proceeding(ctrl, cc_record);
+ }
+ if (cc_record->party_a_status == CC_PARTY_A_AVAILABILITY_BUSY) {
+ /*
+ * The ccSuspend will be sent in a FACILITY or CONNECT
+ * message depending upon the CIS call state.
+ */
+ pri_cc_act_send_cc_suspend(ctrl, cc_record);
+ cc_record->state = CC_STATE_SUSPENDED;
+ } else {
+ /* Start QSIG_CC_T3 */
+ pri_cc_act_start_t_recall(ctrl, cc_record);
+ cc_record->state = CC_STATE_WAIT_CALLBACK;
+ }
+ break;
+ case CC_EVENT_SUSPEND:
+ pri_cc_act_set_a_status_busy(ctrl, cc_record);
+ break;
+ case CC_EVENT_RESUME:
+ pri_cc_act_reset_a_status(ctrl, cc_record);
+ break;
+ case CC_EVENT_TIMEOUT_T_SUPERVISION:
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ pri_cc_act_send_cc_cancel(ctrl, cc_record);
+ pri_cc_act_stop_t_supervision(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ case CC_EVENT_SIGNALING_GONE:
+ /* Signaling link cleared. */
+ pri_cc_act_disassociate_signaling_link(ctrl, cc_record);
+ break;
+ case CC_EVENT_LINK_CANCEL:
+ /* Received ccCancel */
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ pri_cc_act_post_hangup_signaling(ctrl, cc_record);
+ pri_cc_act_stop_t_supervision(ctrl, cc_record);
+ cc_record->state = CC_STATE_WAIT_DESTRUCTION;
+ break;
+ case CC_EVENT_CANCEL:
+ pri_cc_act_send_cc_cancel(ctrl, cc_record);
+ pri_cc_act_stop_t_supervision(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ * \internal
+ * \brief CC FSM Q.SIG monitor CC_STATE_WAIT_CALLBACK.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param cc_record Call completion record to process event.
+ * \param event Event to process.
+ *
+ * \return Nothing
+ */
+static void pri_cc_fsm_qsig_monitor_wait_callback(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
+{
+ switch (event) {
+ case CC_EVENT_RECALL:
+ /* The original call parameters have already been set. */
+ pri_cc_act_queue_setup_recall(ctrl, call, cc_record);
+ pri_cc_act_stop_t_recall(ctrl, cc_record);
+ cc_record->state = CC_STATE_CALLBACK;
+ break;
+ case CC_EVENT_SUSPEND:
+ pri_cc_act_stop_t_recall(ctrl, cc_record);
+ /*
+ * The ccSuspend will be sent in a FACILITY or CONNECT
+ * message depending upon the CIS call state.
+ */
+ pri_cc_act_send_cc_suspend(ctrl, cc_record);
+ cc_record->state = CC_STATE_SUSPENDED;
+ break;
+ case CC_EVENT_TIMEOUT_T_SUPERVISION:
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ pri_cc_act_send_cc_cancel(ctrl, cc_record);
+ pri_cc_act_stop_t_recall(ctrl, cc_record);
+ pri_cc_act_stop_t_supervision(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ case CC_EVENT_SIGNALING_GONE:
+ /* Signaling link cleared. */
+ pri_cc_act_disassociate_signaling_link(ctrl, cc_record);
+ break;
+ case CC_EVENT_LINK_CANCEL:
+ /* Received ccCancel */
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ pri_cc_act_post_hangup_signaling(ctrl, cc_record);
+ pri_cc_act_stop_t_recall(ctrl, cc_record);
+ pri_cc_act_stop_t_supervision(ctrl, cc_record);
+ cc_record->state = CC_STATE_WAIT_DESTRUCTION;
+ break;
+ case CC_EVENT_CANCEL:
+ pri_cc_act_send_cc_cancel(ctrl, cc_record);
+ pri_cc_act_stop_t_recall(ctrl, cc_record);
+ pri_cc_act_stop_t_supervision(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ * \internal
+ * \brief CC FSM Q.SIG monitor CC_STATE_CALLBACK.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param cc_record Call completion record to process event.
+ * \param event Event to process.
+ *
+ * \return Nothing
+ */
+static void pri_cc_fsm_qsig_monitor_callback(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
+{
+ switch (event) {
+ case CC_EVENT_TIMEOUT_T_SUPERVISION:
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ pri_cc_act_send_cc_cancel(ctrl, cc_record);
+ pri_cc_act_stop_t_supervision(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ case CC_EVENT_SIGNALING_GONE:
+ /* Signaling link cleared. */
+ pri_cc_act_disassociate_signaling_link(ctrl, cc_record);
+ break;
+ case CC_EVENT_LINK_CANCEL:
+ /* Received ccCancel */
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ pri_cc_act_post_hangup_signaling(ctrl, cc_record);
+ pri_cc_act_stop_t_supervision(ctrl, cc_record);
+ cc_record->state = CC_STATE_WAIT_DESTRUCTION;
+ break;
+ case CC_EVENT_CANCEL:
+ pri_cc_act_send_cc_cancel(ctrl, cc_record);
+ pri_cc_act_stop_t_supervision(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ * \internal
+ * \brief CC FSM Q.SIG monitor CC_STATE_SUSPENDED.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param cc_record Call completion record to process event.
+ * \param event Event to process.
+ *
+ * \return Nothing
+ */
+static void pri_cc_fsm_qsig_monitor_suspended(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
+{
+ switch (event) {
+ case CC_EVENT_RESUME:
+ pri_cc_act_send_cc_resume(ctrl, cc_record);
+ pri_cc_act_reset_a_status(ctrl, cc_record);
+ cc_record->state = CC_STATE_ACTIVATED;
+ break;
+ case CC_EVENT_TIMEOUT_T_SUPERVISION:
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ pri_cc_act_send_cc_cancel(ctrl, cc_record);
+ pri_cc_act_stop_t_supervision(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ case CC_EVENT_SIGNALING_GONE:
+ /* Signaling link cleared. */
+ pri_cc_act_disassociate_signaling_link(ctrl, cc_record);
+ break;
+ case CC_EVENT_LINK_CANCEL:
+ /* Received ccCancel */
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ pri_cc_act_post_hangup_signaling(ctrl, cc_record);
+ pri_cc_act_stop_t_supervision(ctrl, cc_record);
+ cc_record->state = CC_STATE_WAIT_DESTRUCTION;
+ break;
+ case CC_EVENT_CANCEL:
+ pri_cc_act_send_cc_cancel(ctrl, cc_record);
+ pri_cc_act_stop_t_supervision(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ * \internal
* \brief CC FSM state function type.
*
* \param ctrl D channel controller.
@@ -5933,18 +6401,17 @@
/* *INDENT-ON* */
};
-/*! \todo BUGBUG pri_cc_fsm_qsig_monitor(Q.SIG) not written */
/*! CC FSM Q.SIG monitor state table. */
static const pri_cc_fsm_state pri_cc_fsm_qsig_monitor[CC_STATE_NUM] = {
/* *INDENT-OFF* */
- //[CC_STATE_IDLE] = pri_cc_fsm_qsig_monitor_idle,
- //[CC_STATE_AVAILABLE] = pri_cc_fsm_qsig_monitor_avail,
- //[CC_STATE_REQUESTED] = pri_cc_fsm_qsig_monitor_req,
- //[CC_STATE_WAIT_DESTRUCTION] = pri_cc_fsm_qsig_monitor_wait_destruction,
- //[CC_STATE_ACTIVATED] = pri_cc_fsm_qsig_monitor_activated,
- //[CC_STATE_WAIT_CALLBACK] = pri_cc_fsm_qsig_monitor_wait_callback,
- //[CC_STATE_CALLBACK] = pri_cc_fsm_qsig_monitor_callback,
- //[CC_STATE_SUSPENDED] = pri_cc_fsm_qsig_monitor_suspended,
+ [CC_STATE_IDLE] = pri_cc_fsm_qsig_monitor_idle,
+ [CC_STATE_AVAILABLE] = pri_cc_fsm_qsig_monitor_avail,
+ [CC_STATE_REQUESTED] = pri_cc_fsm_qsig_monitor_req,
+ [CC_STATE_WAIT_DESTRUCTION] = pri_cc_fsm_qsig_monitor_wait_destruction,
+ [CC_STATE_ACTIVATED] = pri_cc_fsm_qsig_monitor_activated,
+ [CC_STATE_WAIT_CALLBACK] = pri_cc_fsm_qsig_monitor_wait_callback,
+ [CC_STATE_CALLBACK] = pri_cc_fsm_qsig_monitor_callback,
+ [CC_STATE_SUSPENDED] = pri_cc_fsm_qsig_monitor_suspended,
/* *INDENT-ON* */
};
@@ -6106,6 +6573,47 @@
}
/*!
+ * \brief Determine if CC is available for Q.SIG outgoing call.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ *
+ * \return Nothing
+ */
+void pri_cc_qsig_determine_available(struct pri *ctrl, q931_call *call)
+{
+ struct pri_cc_record *cc_record;
+
+ if (!call->cc.originated || call->cc.initially_redirected) {
+ /*
+ * The call is not suitable for us to consider CC:
+ * The call was not originated by us.
+ * The call was originally redirected.
+ */
+ return;
+ }
+
+ if (!PRI_MASTER(ctrl)->cc_support) {
+ /*
+ * Blocking the cc-available event effectively
+ * disables call completion for outgoing calls.
+ */
+ return;
+ }
+ if (call->cc.record) {
+ /* Already made available. */
+ return;
+ }
+ cc_record = pri_cc_new_record(ctrl, call);
+ if (!cc_record) {
+ return;
+ }
+ cc_record->original_call = call;
+ call->cc.record = cc_record;
+ pri_cc_event(ctrl, call, cc_record, CC_EVENT_AVAILABLE);
+}
+
+/*!
* \brief Request to activate CC.
*
* \param ctrl D channel controller.
Modified: team/group/ccss/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_internal.h?view=diff&rev=1401&r1=1400&r2=1401
==============================================================================
--- team/group/ccss/pri_internal.h (original)
+++ team/group/ccss/pri_internal.h Wed Dec 23 20:01:23 2009
@@ -615,6 +615,10 @@
unsigned char saved_ie_flags;
/*! TRUE if call needs to be hung up. */
unsigned char hangup_call;
+ /*! TRUE if we originated this call. */
+ unsigned char originated;
+ /*! TRUE if outgoing call was already redirected. */
+ unsigned char initially_redirected;
} cc;
};
@@ -939,6 +943,7 @@
int pri_cc_new_reference_id(struct pri *ctrl);
void pri_cc_delete_record(struct pri *ctrl, struct pri_cc_record *doomed);
struct pri_cc_record *pri_cc_new_record(struct pri *ctrl, q931_call *call);
+void pri_cc_qsig_determine_available(struct pri *ctrl, q931_call *call);
int pri_cc_event(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event);
int q931_cc_timeout(struct pri *ctrl, struct pri_cc_record *cc_record, enum CC_EVENTS event);
void q931_cc_indirect(struct pri *ctrl, struct pri_cc_record *cc_record, void (*func)(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record));
Modified: team/group/ccss/q931.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/q931.c?view=diff&rev=1401&r1=1400&r2=1401
==============================================================================
--- team/group/ccss/q931.c (original)
+++ team/group/ccss/q931.c Wed Dec 23 20:01:23 2009
@@ -4881,6 +4881,12 @@
c->t303_expirycnt++;
c->t303_timer = 0;
+ /*!
+ * \todo XXX Resending the SETUP message loses all facility ies
+ * that the original may have had. Actually any message Q.931
+ * retransmits will lose the facility ies.
+ */
+
if (c->cause != -1) {
/* We got a DISCONNECT, RELEASE, or RELEASE_COMPLETE and no other responses. */
pri_fake_clearing(c);
@@ -4980,6 +4986,10 @@
/* Save the initial cc-parties. */
c->cc.party_a = c->local_id;
+ c->cc.originated = 1;
+ if (c->redirecting.from.number.valid) {
+ c->cc.initially_redirected = 1;
+ }
c->cc.saved_ie_contents.length = 0;
c->cc.saved_ie_flags = 0;
@@ -7044,6 +7054,14 @@
libpri_copy_string(ctrl->ev.ringing.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.ringing.useruserinfo));
c->useruserinfo[0] = '\0';
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_QSIG:
+ pri_cc_qsig_determine_available(ctrl, c);
+ break;
+ default:
+ break;
+ }
+
for (cur = c->apdus; cur; cur = cur->next) {
if (!cur->sent && cur->message == Q931_FACILITY) {
q931_facility(ctrl, c);
@@ -7378,10 +7396,27 @@
ctrl->ev.hangup.aoc_units = c->aoc_units;
libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
c->useruserinfo[0] = '\0';
- if (c->alive)
+
+ if (c->alive) {
+ switch (c->cause) {
+ case PRI_CAUSE_USER_BUSY:
+ case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_QSIG:
+ pri_cc_qsig_determine_available(ctrl, c);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
return Q931_RES_HAVEEVENT;
- else
+ } else {
pri_hangup(ctrl,c,c->cause);
+ }
break;
case Q931_RESTART_ACKNOWLEDGE:
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
More information about the libpri-commits
mailing list