[libpri-commits] rmudgett: branch group/ccss r1388 - in /team/group/ccss: ./ doc/
SVN commits to the libpri project
libpri-commits at lists.digium.com
Tue Dec 15 17:17:58 CST 2009
Author: rmudgett
Date: Tue Dec 15 17:17:55 2009
New Revision: 1388
URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1388
Log:
PTMP monitor FSM written. Needs testing.
* Added some sanity checks to CC API functions.
* Added CC PTMP monitor FSM pseudo code document files in the doc
directory.
Added:
team/group/ccss/doc/cc_ptmp_monitor.fsm (with props)
team/group/ccss/doc/cc_ptmp_monitor_flattened.fsm (with props)
Modified:
team/group/ccss/libpri.h
team/group/ccss/pri_cc.c
team/group/ccss/pri_facility.c
team/group/ccss/pri_facility.h
team/group/ccss/pri_internal.h
Added: team/group/ccss/doc/cc_ptmp_monitor.fsm
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/doc/cc_ptmp_monitor.fsm?view=auto&rev=1388
==============================================================================
--- team/group/ccss/doc/cc_ptmp_monitor.fsm (added)
+++ team/group/ccss/doc/cc_ptmp_monitor.fsm Tue Dec 15 17:17:55 2009
@@ -1,0 +1,177 @@
+/*
+ * FSM pseudo code used in the design/implementation of the CC PTMP monitor.
+ *
+ * The CCBSStatusRequest messages are handled independently from this FSM.
+ *
+ * The CCBSInterrogate/CCNRInterrogate messages are initiated by a dialplan
+ * application/AMI/CLI (future) and are handled outside of this FSM.
+ */
+FSM CC_PTMP_Monitor
+{
+ State CC_STATE_IDLE {
+ Init {
+ }
+ Prolog {
+ Action Set_Selfdestruct;
+ }
+ Stimulus CC_EVENT_AVAILABLE {
+ /*
+ * Before event is posted:
+ * Received CallInfoRetain
+ * Created cc_record
+ * Saved CallLinkageID
+ */
+ Action Pass_Up_CC_Available;
+ Next_State CC_STATE_AVAILABLE;
+ }
+ Stimulus CC_EVENT_CANCEL {
+ Action Set_Selfdestruct;
+ }
+ }
+ State CC_STATE_AVAILABLE {
+ /*
+ * For PTMP TE mode the T_RETENTION timer is not defined. However,
+ * we will use it anyway in this state to protect our resources from
+ * leaks caused by the network cable being disconnected. This
+ * timer should be set much longer than the network so normally
+ * the CC records will be cleaned up by network activity.
+ */
+ Epilog {
+ Action Stop_T_RETENTION;
+ }
+ Stimulus CC_EVENT_MSG_RELEASE {
+ Action Stop_T_RETENTION;
+ Action Start_T_RETENTION;
+ }
+ Stimulus CC_EVENT_MSG_RELEASE_COMPLETE {
+ Action Stop_T_RETENTION;
+ Action Start_T_RETENTION;
+ }
+ Stimulus CC_EVENT_CC_REQUEST {
+ /* cc_record->is_ccnr is set before event posted. */
+ Action Queue_CC_Request;
+ Action Start_T_ACTIVATE;
+ Next_State CC_STATE_REQUESTED;
+ }
+ Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
+ /*
+ * Received EraseCallLinkageID
+ * or T_RETENTION really timed out.
+ */
+ Action Pass_Up_CC_Cancel;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_CANCEL {
+ Next_State CC_STATE_IDLE;
+ }
+ }
+ State CC_STATE_REQUESTED {
+ Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
+ /*
+ * Before event is posted:
+ * Received CCBSRequest/CCNRRequest response
+ * Saved CCBSReference
+ */
+ Action Relese_LinkID;
+ Action Pass_Up_CC_Req_Rsp_Success;
+ Action Stop_T_ACTIVATE;
+ Next_State CC_STATE_ACTIVATED;
+ }
+ Stimulus CC_EVENT_CC_REQUEST_FAIL {
+ Action Pass_Up_CC_Req_Rsp_Fail(error/reject, code);
+ Action Pass_Up_CC_Cancel;
+ Action Stop_T_ACTIVATE;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
+ Action Pass_Up_CC_Req_Rsp_Timeout;
+ Action Pass_Up_CC_Cancel;
+ Action Stop_T_ACTIVATE;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_LINK_CANCEL {
+ /* Received CCBSErase */
+ /* Claim it was a timeout */
+ Action Pass_Up_CC_Req_Rsp_Timeout;
+ Action Pass_Up_CC_Cancel;
+ Action Stop_T_ACTIVATE;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_CANCEL {
+ Next_State CC_STATE_WAIT_DESTRUCTION;
+ }
+ }
+ State CC_STATE_WAIT_DESTRUCTION {
+ /* We were in the middle of a cc-request when we were asked to cancel. */
+ Epilog {
+ Action Stop_T_ACTIVATE;
+ /* Claim it was a timeout */
+ Action Pass_Up_CC_Req_Rsp_Timeout;
+ }
+ Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
+ /*
+ * Before event is posted:
+ * Received CCBSRequest/CCNRRequest response
+ * Saved CCBSReference
+ */
+ Action Send_CC_Deactivate_Req;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_CC_REQUEST_FAIL {
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_LINK_CANCEL {
+ /* Received CCBSErase */
+ Next_State CC_STATE_IDLE;
+ }
+ }
+ State CC_STATE_ACTIVATED {
+ Prolog {
+ /*
+ * Start T_CCBS2 or T_CCNR2 depending upon CC mode.
+ * For PTMP TE mode these timers are not defined. However,
+ * we will use them anyway to protect our resources from leaks
+ * caused by the network cable being disconnected. These
+ * timers should be set much longer than the network
+ * so normally the CC records will be cleaned up by network
+ * activity.
+ */
+ Action Start_T_CCBS2;
+ }
+ Epilog {
+ Action Stop_T_CCBS2;
+ }
+ Stimulus CC_EVENT_B_FREE {
+ /* Received CCBSBFree */
+ Action Pass_Up_B_Free;
+ }
+ Stimulus CC_EVENT_REMOTE_USER_FREE {
+ /* Received CCBSRemoteUserFree */
+ Action Pass_Up_Remote_User_Free;
+ }
+ Stimulus CC_EVENT_STOP_ALERTING {
+ Action Pass_Up_Stop_Alerting;
+ }
+ Stimulus CC_EVENT_RECALL {
+ /* The original call parameters have already been set. */
+ Action Queue_SETUP_Recall;
+ }
+ Stimulus CC_EVENT_TIMEOUT_T_CCBS2 {
+ Action Send_CC_Deactivate_Req;
+ Action Pass_Up_CC_Cancel;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_LINK_CANCEL {
+ /* Received CCBSErase */
+ Action Pass_Up_CC_Cancel;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_CANCEL {
+ Action Send_CC_Deactivate_Req;
+ Next_State CC_STATE_IDLE;
+ }
+ }
+}
Propchange: team/group/ccss/doc/cc_ptmp_monitor.fsm
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/group/ccss/doc/cc_ptmp_monitor.fsm
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/group/ccss/doc/cc_ptmp_monitor.fsm
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/group/ccss/doc/cc_ptmp_monitor_flattened.fsm
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/doc/cc_ptmp_monitor_flattened.fsm?view=auto&rev=1388
==============================================================================
--- team/group/ccss/doc/cc_ptmp_monitor_flattened.fsm (added)
+++ team/group/ccss/doc/cc_ptmp_monitor_flattened.fsm Tue Dec 15 17:17:55 2009
@@ -1,0 +1,189 @@
+/*
+ * FSM pseudo code used in the design/implementation of the CC PTMP monitor.
+ *
+ * The CCBSStatusRequest messages are handled independently from this FSM.
+ *
+ * The CCBSInterrogate/CCNRInterrogate messages are initiated by a dialplan
+ * application/AMI/CLI (future) and are handled outside of this FSM.
+ */
+FSM CC_PTMP_Monitor
+{
+ State CC_STATE_IDLE {
+ Stimulus CC_EVENT_AVAILABLE {
+ /*
+ * Before event is posted:
+ * Received CallInfoRetain
+ * Created cc_record
+ * Saved CallLinkageID
+ */
+ Action Pass_Up_CC_Available;
+ Next_State CC_STATE_AVAILABLE;
+ }
+ Stimulus CC_EVENT_CANCEL {
+ Action Set_Selfdestruct;
+ }
+ }
+ State CC_STATE_AVAILABLE {
+ /*
+ * For PTMP TE mode the T_RETENTION timer is not defined. However,
+ * we will use it anyway in this state to protect our resources from
+ * leaks caused by the network cable being disconnected. This
+ * timer should be set much longer than the network so normally
+ * the CC records will be cleaned up by network activity.
+ */
+ Stimulus CC_EVENT_MSG_RELEASE {
+ Action Stop_T_RETENTION;
+ Action Start_T_RETENTION;
+ }
+ Stimulus CC_EVENT_MSG_RELEASE_COMPLETE {
+ Action Stop_T_RETENTION;
+ Action Start_T_RETENTION;
+ }
+ Stimulus CC_EVENT_CC_REQUEST {
+ /* cc_record->is_ccnr is set before event posted. */
+ Action Queue_CC_Request;
+ Action Start_T_ACTIVATE;
+ Action Stop_T_RETENTION;
+ Next_State CC_STATE_REQUESTED;
+ }
+ Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
+ /*
+ * Received EraseCallLinkageID
+ * or T_RETENTION really timed out.
+ */
+ Action Pass_Up_CC_Cancel;
+ Action Stop_T_RETENTION;
+ Action Set_Selfdestruct;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_CANCEL {
+ Action Stop_T_RETENTION;
+ Action Set_Selfdestruct;
+ Next_State CC_STATE_IDLE;
+ }
+ }
+ State CC_STATE_REQUESTED {
+ Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
+ /*
+ * Before event is posted:
+ * Received CCBSRequest/CCNRRequest response
+ * Saved CCBSReference
+ */
+ Action Relese_LinkID;
+ Action Pass_Up_CC_Req_Rsp_Success;
+ Action Stop_T_ACTIVATE;
+ /*
+ * Start T_CCBS2 or T_CCNR2 depending upon CC mode.
+ * For PTMP TE mode these timers are not defined. However,
+ * we will use them anyway to protect our resources from leaks
+ * caused by the network cable being disconnected. These
+ * timers should be set much longer than the network
+ * so normally the CC records will be cleaned up by network
+ * activity.
+ */
+ Action Start_T_CCBS2;
+ Next_State CC_STATE_ACTIVATED;
+ }
+ Stimulus CC_EVENT_CC_REQUEST_FAIL {
+ Action Pass_Up_CC_Req_Rsp_Fail(error/reject, code);
+ Action Pass_Up_CC_Cancel;
+ Action Stop_T_ACTIVATE;
+ Action Set_Selfdestruct;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
+ Action Pass_Up_CC_Req_Rsp_Timeout;
+ Action Pass_Up_CC_Cancel;
+ Action Stop_T_ACTIVATE;
+ Action Set_Selfdestruct;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_LINK_CANCEL {
+ /* Received CCBSErase */
+ /* Claim it was a timeout */
+ Action Pass_Up_CC_Req_Rsp_Timeout;
+ Action Pass_Up_CC_Cancel;
+ Action Stop_T_ACTIVATE;
+ Action Set_Selfdestruct;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_CANCEL {
+ Next_State CC_STATE_WAIT_DESTRUCTION;
+ }
+ }
+ State CC_STATE_WAIT_DESTRUCTION {
+ /* We were in the middle of a cc-request when we were asked to cancel. */
+ Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
+ /*
+ * Before event is posted:
+ * Received CCBSRequest/CCNRRequest response
+ * Saved CCBSReference
+ */
+ Action Send_CC_Deactivate_Req;
+ Action Stop_T_ACTIVATE;
+ /* Claim it was a timeout */
+ Action Pass_Up_CC_Req_Rsp_Timeout;
+ Action Set_Selfdestruct;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_CC_REQUEST_FAIL {
+ Action Stop_T_ACTIVATE;
+ /* Claim it was a timeout */
+ Action Pass_Up_CC_Req_Rsp_Timeout;
+ Action Set_Selfdestruct;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
+ Action Stop_T_ACTIVATE;
+ /* Claim it was a timeout */
+ Action Pass_Up_CC_Req_Rsp_Timeout;
+ Action Set_Selfdestruct;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_LINK_CANCEL {
+ /* Received CCBSErase */
+ Action Stop_T_ACTIVATE;
+ /* Claim it was a timeout */
+ Action Pass_Up_CC_Req_Rsp_Timeout;
+ Action Set_Selfdestruct;
+ Next_State CC_STATE_IDLE;
+ }
+ }
+ State CC_STATE_ACTIVATED {
+ Stimulus CC_EVENT_B_FREE {
+ /* Received CCBSBFree */
+ Action Pass_Up_B_Free;
+ }
+ Stimulus CC_EVENT_REMOTE_USER_FREE {
+ /* Received CCBSRemoteUserFree */
+ Action Pass_Up_Remote_User_Free;
+ }
+ Stimulus CC_EVENT_STOP_ALERTING {
+ Action Pass_Up_Stop_Alerting;
+ }
+ Stimulus CC_EVENT_RECALL {
+ /* The original call parameters have already been set. */
+ Action Queue_SETUP_Recall;
+ }
+ Stimulus CC_EVENT_TIMEOUT_T_CCBS2 {
+ Action Send_CC_Deactivate_Req;
+ Action Pass_Up_CC_Cancel;
+ Action Stop_T_CCBS2;
+ Action Set_Selfdestruct;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_LINK_CANCEL {
+ /* Received CCBSErase */
+ Action Pass_Up_CC_Cancel;
+ Action Stop_T_CCBS2;
+ Action Set_Selfdestruct;
+ Next_State CC_STATE_IDLE;
+ }
+ Stimulus CC_EVENT_CANCEL {
+ Action Send_CC_Deactivate_Req;
+ Action Stop_T_CCBS2;
+ Action Set_Selfdestruct;
+ Next_State CC_STATE_IDLE;
+ }
+ }
+}
Propchange: team/group/ccss/doc/cc_ptmp_monitor_flattened.fsm
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/group/ccss/doc/cc_ptmp_monitor_flattened.fsm
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/group/ccss/doc/cc_ptmp_monitor_flattened.fsm
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/group/ccss/libpri.h
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/libpri.h?view=diff&rev=1388&r1=1387&r2=1388
==============================================================================
--- team/group/ccss/libpri.h (original)
+++ team/group/ccss/libpri.h Tue Dec 15 17:17:55 2009
@@ -599,6 +599,7 @@
int fail_code;
/*!
* \brief TRUE if negotiated to retain CC service if B busy again.
+ * \note Valid when status is success.
*/
int retain_service;
};
@@ -1449,7 +1450,7 @@
void pri_cc_remote_user_free(struct pri *ctrl, long cc_id);
void pri_cc_b_free(struct pri *ctrl, long cc_id);
void pri_cc_stop_alerting(struct pri *ctrl, long cc_id);
-int pri_cc_status_req(struct pri *ctrl, long cc_id);
+void pri_cc_status_req(struct pri *ctrl, long cc_id);
void pri_cc_status_req_rsp(struct pri *ctrl, long cc_id, int status);
void pri_cc_status(struct pri *ctrl, long cc_id, int status);
int pri_cc_call(struct pri *ctrl, long cc_id, q931_call *call, struct pri_sr *req);
Modified: team/group/ccss/pri_cc.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_cc.c?view=diff&rev=1388&r1=1387&r2=1388
==============================================================================
--- team/group/ccss/pri_cc.c (original)
+++ team/group/ccss/pri_cc.c Tue Dec 15 17:17:55 2009
@@ -299,6 +299,8 @@
cc_record->party_b_is_remote = call->cc.party_b_is_remote;
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;
+ cc_record->option.retain_service = ctrl->cc.option.retain_service;
/*! \todo BUGBUG need more initialization?? */
/*
@@ -694,6 +696,120 @@
/*!
* \internal
+ * \brief Encode ETSI PTMP CCBSRequest/CCNRRequest message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param pos Starting position to encode the facility ie contents.
+ * \param end End of facility ie contents encoding data buffer.
+ * \param cc_record Call completion record to process event.
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *enc_etsi_ptmp_cc_request(struct pri *ctrl,
+ unsigned char *pos, unsigned char *end, struct pri_cc_record *cc_record)
+{
+ struct rose_msg_invoke msg;
+
+ pos = facility_encode_header(ctrl, pos, end, NULL);
+ if (!pos) {
+ return NULL;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ msg.invoke_id = get_invokeid(ctrl);
+ msg.operation = cc_record->is_ccnr ? ROSE_ETSI_CCNRRequest : ROSE_ETSI_CCBSRequest;
+
+ msg.args.etsi.CCBSRequest.call_linkage_id = cc_record->call_linkage_id;
+
+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+ return pos;
+}
+
+/*!
+ * \internal
+ * \brief Encode ETSI PTMP CCBSDeactivate message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param pos Starting position to encode the facility ie contents.
+ * \param end End of facility ie contents encoding data buffer.
+ * \param cc_record Call completion record to process event.
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *enc_etsi_ptmp_cc_deactivate(struct pri *ctrl,
+ unsigned char *pos, unsigned char *end, struct pri_cc_record *cc_record)
+{
+ struct rose_msg_invoke msg;
+
+ pos = facility_encode_header(ctrl, pos, end, NULL);
+ if (!pos) {
+ return NULL;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ msg.invoke_id = get_invokeid(ctrl);
+ msg.operation = ROSE_ETSI_CCBSDeactivate;
+
+ msg.args.etsi.CCBSDeactivate.ccbs_reference = cc_record->ccbs_reference_id;
+
+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+ return pos;
+}
+
+/*!
+ * \internal
+ * \brief Encode and queue an CCBSDeactivate message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param call Call leg from which to encode CCBSDeactivate.
+ * \param cc_record Call completion record to process event.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int rose_cc_deactivate_encode(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record)
+{
+ unsigned char buffer[256];
+ unsigned char *end;
+
+ end =
+ enc_etsi_ptmp_cc_deactivate(ctrl, buffer, buffer + sizeof(buffer), cc_record);
+ if (!end) {
+ return -1;
+ }
+
+ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
+}
+
+/*!
+ * \internal
+ * \brief Encode and send an CCBSDeactivate message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param call Call leg from which to encode CCBSDeactivate.
+ * \param cc_record Call completion record to process event.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int send_cc_deactivate_req(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record)
+{
+ if (rose_cc_deactivate_encode(ctrl, call, cc_record)
+ || q931_facility(ctrl, call)) {
+ pri_message(ctrl,
+ "Could not schedule facility message for CCBSDeactivate.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*!
+ * \internal
* \brief Encode ETSI PTMP CCBSBFree message.
*
* \param ctrl D channel controller for diagnostic messages or global options.
@@ -990,6 +1106,80 @@
/*!
* \internal
+ * \brief Encode ETSI PTMP CCBSCall message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param pos Starting position to encode the facility ie contents.
+ * \param end End of facility ie contents encoding data buffer.
+ * \param cc_record Call completion record to process event.
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *enc_etsi_ptmp_cc_recall(struct pri *ctrl, unsigned char *pos,
+ unsigned char *end, struct pri_cc_record *cc_record)
+{
+ struct rose_msg_invoke msg;
+
+ pos = facility_encode_header(ctrl, pos, end, NULL);
+ if (!pos) {
+ return NULL;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ msg.invoke_id = get_invokeid(ctrl);
+ msg.operation = ROSE_ETSI_CCBSCall;
+
+ msg.args.etsi.CCBSCall.ccbs_reference = cc_record->ccbs_reference_id;
+
+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+ return pos;
+}
+
+/*!
+ * \internal
+ * \brief Encode and queue a cc-recall message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param call Call leg from which to encode cc-recall.
+ * \param cc_record Call completion record to process event.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int rose_cc_recall_encode(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record)
+{
+ unsigned char buffer[256];
+ unsigned char *end;
+
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ end =
+ enc_etsi_ptmp_cc_recall(ctrl, buffer, buffer + sizeof(buffer), cc_record);
+ } else {
+ end =
+ enc_etsi_ptp_cc_operation(ctrl, buffer, buffer + sizeof(buffer),
+ ROSE_ETSI_CCBS_T_Call);
+ }
+ break;
+ case PRI_SWITCH_QSIG:
+ /*! \todo BUGBUG rose_cc_recall_encode(Q.SIG) not written */
+ return -1;
+ default:
+ return -1;
+ }
+ if (!end) {
+ return -1;
+ }
+
+ return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL);
+}
+
+/*!
+ * \internal
* \brief Copy the cc information into the ETSI ROSE call-information record.
*
* \param ctrl D channel controller for diagnostic messages or global options.
@@ -1411,6 +1601,17 @@
case CC_EVENT_MSG_RELEASE_COMPLETE:
str = "CC_EVENT_MSG_RELEASE_COMPLETE";
break;
+ case CC_EVENT_TIMEOUT_T_ACTIVATE:
+ str = "CC_EVENT_TIMEOUT_T_ACTIVATE";
+ break;
+#if 0
+ case CC_EVENT_TIMEOUT_T_DEACTIVATE:
+ str = "CC_EVENT_TIMEOUT_T_DEACTIVATE";
+ break;
+#endif
+ case CC_EVENT_TIMEOUT_T_INTERROGATE:
+ str = "CC_EVENT_TIMEOUT_T_INTERROGATE";
+ break;
case CC_EVENT_TIMEOUT_T_RETENTION:
str = "CC_EVENT_TIMEOUT_T_RETENTION";
break;
@@ -1857,6 +2058,175 @@
/*!
* \internal
+ * \brief FSM action to stop the PTMP T_ACTIVATE timer.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_record Call completion record to process event.
+ *
+ * \return Nothing
+ */
+static void pri_cc_act_stop_t_activate(struct pri *ctrl, struct pri_cc_record *cc_record)
+{
+ struct apdu_event *msg;
+
+ PRI_CC_ACT_DEBUG_OUTPUT(ctrl);
+
+ if (!cc_record->signaling) {
+ return;
+ }
+ msg = pri_call_apdu_find(cc_record->signaling, cc_record->t_activate_invoke_id);
+ if (msg) {
+ pri_call_apdu_delete(cc_record->signaling, msg);
+ }
+}
+
+/*!
+ * \internal
+ * \brief cc-request PTMP response callback function.
+ *
+ * \param reason Reason callback is called.
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param apdu APDU queued entry. Do not change!
+ * \param msg APDU response message data. (NULL if was not the reason called.)
+ *
+ * \return TRUE if no more responses are expected.
+ */
+static int pri_cc_req_response_ptmp(enum APDU_CALLBACK_REASON reason, struct pri *ctrl, struct q931_call *call, struct apdu_event *apdu, const union apdu_msg_data *msg)
+{
+ struct pri_cc_record *cc_record;
+
+ cc_record = apdu->response.user.ptr;
+
+ switch (reason) {
+ case APDU_CALLBACK_REASON_TIMEOUT:
+ pri_cc_event(ctrl, call, cc_record, CC_EVENT_TIMEOUT_T_ACTIVATE);
+ break;
+ case APDU_CALLBACK_REASON_MSG_RESULT:
+ /*
+ * Since we received this facility, we will not be allocating any
+ * reference and linkage id's.
+ */
+ cc_record->ccbs_reference_id =
+ msg->result->args.etsi.CCBSRequest.ccbs_reference & 0x7F;
+ cc_record->option.recall_mode = msg->result->args.etsi.CCBSRequest.recall_mode;
+
+ pri_cc_event(ctrl, call, cc_record, CC_EVENT_CC_REQUEST_ACCEPT);
+ break;
+ case APDU_CALLBACK_REASON_MSG_ERROR:
+ cc_record->msg.cc_req_rsp.reason = reason;
+ cc_record->msg.cc_req_rsp.code = msg->error->code;
+
+ pri_cc_event(ctrl, call, cc_record, CC_EVENT_CC_REQUEST_FAIL);
+ break;
+ case APDU_CALLBACK_REASON_MSG_REJECT:
+ cc_record->msg.cc_req_rsp.reason = reason;
+ cc_record->msg.cc_req_rsp.code = msg->reject->code;
+
+ pri_cc_event(ctrl, call, cc_record, CC_EVENT_CC_REQUEST_FAIL);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * No more reponses are really expected.
+ * However, the FSM will be removing the apdu_event itself instead.
+ */
+ return 0;
+}
+
+/*!
+ * \internal
+ * \brief Encode and queue a cc-request message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param call Call leg from which to encode cc-request.
+ * \param cc_record Call completion record to process event.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int rose_cc_request(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record)
+{
+ unsigned char buffer[256];
+ unsigned char *end;
+ struct apdu_callback_data response;
+ int msgtype;
+
+ memset(&response, 0, sizeof(response));
+
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (q931_is_ptmp(ctrl)) {
+ end =
+ enc_etsi_ptmp_cc_request(ctrl, buffer, buffer + sizeof(buffer),
+ cc_record);
+ msgtype = Q931_FACILITY;
+ response.callback = pri_cc_req_response_ptmp;
+ } else {
+ /* \todo BUGBUG rose_cc_request(PTP) not written. */
+ //msgtype = Q931_REGISTER;
+ //response.callback = pri_cc_req_response_ptp;
+ return -1;
+ }
+ response.timeout_time = ctrl->timers[PRI_TIMER_T_ACTIVATE];
+ break;
+ case PRI_SWITCH_QSIG:
+ /* \todo BUGBUG rose_cc_request(Q.SIG) not written. */
+ //msgtype = Q931_SETUP;
+ //response.callback = pri_cc_req_response_qsig;
+ //response.timeout_time = ctrl->timers[PRI_TIMER_QSIG_CC_T1];
+ return -1;
+ default:
+ return -1;
+ }
+ if (!end) {
+ return -1;
+ }
+
+ response.user.ptr = cc_record;
+ response.invoke_id = ctrl->last_invoke;
+ cc_record->t_activate_invoke_id = ctrl->last_invoke;
+ return pri_call_apdu_queue(call, msgtype, buffer, end - buffer, &response);
+}
+
+/*!
+ * \internal
+ * \brief FSM action to queue the cc-request message.
+ *
+ * \param ctrl D channel controller.
+ * \param call Call leg from which to encode cc-request.
+ * \param cc_record Call completion record to process event.
+ *
+ * \return Nothing
+ */
+static void pri_cc_act_queue_cc_request(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record)
+{
+ PRI_CC_ACT_DEBUG_OUTPUT(ctrl);
+ if (rose_cc_request(ctrl, call, cc_record)) {
+ pri_message(ctrl, "Could not queue message for cc-request.\n");
+ }
+}
+
+/*!
+ * \internal
+ * \brief FSM action to send the CCBSDeactivate message.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_record Call completion record to process event.
+ *
+ * \return Nothing
+ */
+static void pri_cc_act_send_cc_deactivate_req(struct pri *ctrl, struct pri_cc_record *cc_record)
+{
+ PRI_CC_ACT_DEBUG_OUTPUT(ctrl);
+ send_cc_deactivate_req(ctrl, cc_record->signaling, cc_record);
+}
+
+/*!
+ * \internal
* \brief FSM action to send the CCBSBFree message.
*
* \param ctrl D channel controller.
@@ -2183,6 +2553,185 @@
/*!
* \internal
+ * \brief FSM action to pass up CC available to upper layer.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_record Call completion record to process event.
+ *
+ * \return Nothing
+ */
+static void pri_cc_act_pass_up_cc_available(struct pri *ctrl, struct pri_cc_record *cc_record)
+{
+ struct pri_subcommand *subcmd;
+
+ PRI_CC_ACT_DEBUG_OUTPUT(ctrl);
+
+ subcmd = q931_alloc_subcommand(ctrl);
+ if (!subcmd) {
+ return;
+ }
+
+ subcmd->cmd = PRI_SUBCMD_CC_AVAILABLE;
+ subcmd->u.cc_available.cc_id = cc_record->record_id;
+}
+
+/*!
+ * \internal
+ * \brief FSM action to pass up CC request response is success to upper layer.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_record Call completion record to process event.
+ *
+ * \return Nothing
+ */
+static void pri_cc_act_pass_up_cc_req_rsp_success(struct pri *ctrl, struct pri_cc_record *cc_record)
+{
+ struct pri_subcommand *subcmd;
+
+ PRI_CC_ACT_DEBUG_OUTPUT(ctrl);
+
+ subcmd = q931_alloc_subcommand(ctrl);
+ if (!subcmd) {
+ return;
+ }
+
+ subcmd->cmd = PRI_SUBCMD_CC_REQ_RSP;
+ subcmd->u.cc_request_rsp.cc_id = cc_record->record_id;
+ subcmd->u.cc_request_rsp.status = 0;/* success */
+ subcmd->u.cc_request_rsp.fail_code = 0;
+ subcmd->u.cc_request_rsp.retain_service = cc_record->option.retain_service;
+}
+
+/*!
+ * \internal
+ * \brief FSM action to pass up CC request response is failed to upper layer.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_record Call completion record to process event.
+ *
+ * \return Nothing
+ */
+static void pri_cc_act_pass_up_cc_req_rsp_fail(struct pri *ctrl, struct pri_cc_record *cc_record)
+{
+ struct pri_subcommand *subcmd;
+
+ PRI_CC_ACT_DEBUG_OUTPUT(ctrl);
+
+ subcmd = q931_alloc_subcommand(ctrl);
+ if (!subcmd) {
+ return;
+ }
+
+ subcmd->cmd = PRI_SUBCMD_CC_REQ_RSP;
+ subcmd->u.cc_request_rsp.cc_id = cc_record->record_id;
+ subcmd->u.cc_request_rsp.status =
+ (cc_record->msg.cc_req_rsp.reason == APDU_CALLBACK_REASON_MSG_ERROR)
+ ? 2 /* error */ : 3 /* reject */;
+ subcmd->u.cc_request_rsp.fail_code = cc_record->msg.cc_req_rsp.code;
+ subcmd->u.cc_request_rsp.retain_service = 0;
+}
+
+/*!
+ * \internal
+ * \brief FSM action to pass up CC request response is timeout to upper layer.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_record Call completion record to process event.
+ *
+ * \return Nothing
+ */
+static void pri_cc_act_pass_up_cc_req_rsp_timeout(struct pri *ctrl, struct pri_cc_record *cc_record)
+{
+ struct pri_subcommand *subcmd;
+
+ PRI_CC_ACT_DEBUG_OUTPUT(ctrl);
+
+ subcmd = q931_alloc_subcommand(ctrl);
+ if (!subcmd) {
+ return;
+ }
+
+ subcmd->cmd = PRI_SUBCMD_CC_REQ_RSP;
+ subcmd->u.cc_request_rsp.cc_id = cc_record->record_id;
+ subcmd->u.cc_request_rsp.status = 1;/* timeout */
+ subcmd->u.cc_request_rsp.fail_code = 0;
+ subcmd->u.cc_request_rsp.retain_service = 0;
+}
+
+/*!
+ * \internal
+ * \brief FSM action to pass up CC B free to upper layer.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_record Call completion record to process event.
+ *
+ * \return Nothing
+ */
+static void pri_cc_act_pass_up_b_free(struct pri *ctrl, struct pri_cc_record *cc_record)
+{
+ struct pri_subcommand *subcmd;
+
+ PRI_CC_ACT_DEBUG_OUTPUT(ctrl);
+
+ subcmd = q931_alloc_subcommand(ctrl);
+ if (!subcmd) {
+ return;
+ }
+
+ subcmd->cmd = PRI_SUBCMD_CC_B_FREE;
+ subcmd->u.cc_b_free.cc_id = cc_record->record_id;
+}
+
+/*!
+ * \internal
+ * \brief FSM action to pass up CC remote user free to upper layer.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_record Call completion record to process event.
+ *
+ * \return Nothing
+ */
+static void pri_cc_act_pass_up_remote_user_free(struct pri *ctrl, struct pri_cc_record *cc_record)
+{
+ struct pri_subcommand *subcmd;
+
+ PRI_CC_ACT_DEBUG_OUTPUT(ctrl);
+
+ subcmd = q931_alloc_subcommand(ctrl);
+ if (!subcmd) {
+ return;
+ }
+
+ subcmd->cmd = PRI_SUBCMD_CC_REMOTE_USER_FREE;
+ subcmd->u.cc_remote_user_free.cc_id = cc_record->record_id;
+}
+
+/*!
+ * \internal
+ * \brief FSM action to pass up stop alerting to upper layer.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_record Call completion record to process event.
+ *
+ * \return Nothing
+ */
+static void pri_cc_act_pass_up_stop_alerting(struct pri *ctrl, struct pri_cc_record *cc_record)
+{
+ struct pri_subcommand *subcmd;
+
+ PRI_CC_ACT_DEBUG_OUTPUT(ctrl);
+
+ subcmd = q931_alloc_subcommand(ctrl);
+ if (!subcmd) {
+ return;
+ }
+
+ subcmd->cmd = PRI_SUBCMD_CC_STOP_ALERTING;
+ subcmd->u.cc_stop_alerting.cc_id = cc_record->record_id;
+}
+
+/*!
+ * \internal
* \brief FSM action to send error response to recall attempt.
*
* \param ctrl D channel controller.
@@ -2196,6 +2745,22 @@
PRI_CC_ACT_DEBUG_OUTPUT(ctrl);
rose_error_msg_encode(ctrl, cc_record->response.signaling, Q931_ANY_MESSAGE,
cc_record->response.invoke_id, code);
+}
+
+/*!
+ * \internal
+ * \brief FSM action to queue CC recall marker.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param cc_record Call completion record to process event.
+ *
+ * \return Nothing
+ */
+static void pri_cc_act_queue_setup_recall(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record)
+{
+ PRI_CC_ACT_DEBUG_OUTPUT(ctrl);
+ rose_cc_recall_encode(ctrl, call, cc_record);
}
/*!
@@ -2806,6 +3371,266 @@
/*!
* \internal
+ * \brief CC FSM PTMP 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_ptmp_monitor_idle(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
+{
+ switch (event) {
+ case CC_EVENT_AVAILABLE:
+ /*
+ * Before event is posted:
+ * Received CallInfoRetain
+ * Created cc_record
+ * Saved CallLinkageID
+ */
+ 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 PTMP 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_ptmp_monitor_avail(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
+{
+ /*
+ * For PTMP TE mode the T_RETENTION timer is not defined. However,
+ * we will use it anyway in this state to protect our resources from
+ * leaks caused by the network cable being disconnected. This
+ * timer should be set much longer than the network so normally
+ * the CC records will be cleaned up by network activity.
+ */
+ switch (event) {
+ case CC_EVENT_MSG_RELEASE:
+ case CC_EVENT_MSG_RELEASE_COMPLETE:
+ pri_cc_act_stop_t_retention(ctrl, cc_record);
+ pri_cc_act_start_t_retention(ctrl, cc_record);
+ break;
+ case CC_EVENT_CC_REQUEST:
+ /* cc_record->is_ccnr is set before event posted. */
+ pri_cc_act_queue_cc_request(ctrl, call, cc_record);
+ //pri_cc_act_start_t_activate(ctrl, cc_record);
+ pri_cc_act_stop_t_retention(ctrl, cc_record);
+ cc_record->state = CC_STATE_REQUESTED;
+ break;
+ case CC_EVENT_TIMEOUT_T_RETENTION:
+ /*
+ * Received EraseCallLinkageID
+ * or T_RETENTION really timed out.
+ */
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ pri_cc_act_stop_t_retention(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_stop_t_retention(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 PTMP 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_ptmp_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:
+ /*
+ * Before event is posted:
+ * Received CCBSRequest/CCNRRequest response
+ * Saved CCBSReference
+ */
+ pri_cc_act_release_link_id(ctrl, cc_record);
+ pri_cc_act_pass_up_cc_req_rsp_success(ctrl, cc_record);
+ pri_cc_act_stop_t_activate(ctrl, cc_record);
+ /*
+ * Start T_CCBS2 or T_CCNR2 depending upon CC mode.
+ * For PTMP TE mode these timers are not defined. However,
+ * we will use them anyway to protect our resources from leaks
+ * caused by the network cable being disconnected. These
+ * timers should be set much longer than the network
+ * so normally the CC records will be cleaned up by network
+ * activity.
+ */
+ pri_cc_act_start_t_ccbs2(ctrl, cc_record);
+ cc_record->state = CC_STATE_ACTIVATED;
+ break;
+ case CC_EVENT_CC_REQUEST_FAIL:
+ pri_cc_act_pass_up_cc_req_rsp_fail(ctrl, cc_record);
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ 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_TIMEOUT_T_ACTIVATE:
+ 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_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_LINK_CANCEL:
+ /* Received CCBSErase */
+ /* 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_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_CANCEL:
+ cc_record->state = CC_STATE_WAIT_DESTRUCTION;
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ * \internal
+ * \brief CC FSM PTMP 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_ptmp_monitor_wait_destruction(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
+{
+ /* We were in the middle of a cc-request when we were asked to cancel. */
+ switch (event) {
+ case CC_EVENT_CC_REQUEST_ACCEPT:
+ /*
+ * Before event is posted:
+ * Received CCBSRequest/CCNRRequest response
+ * Saved CCBSReference
+ */
+ pri_cc_act_send_cc_deactivate_req(ctrl, cc_record);
+ 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_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);
+ /* Claim it was a timeout */
+ pri_cc_act_pass_up_cc_req_rsp_timeout(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ case CC_EVENT_TIMEOUT_T_ACTIVATE:
+ 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_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ case CC_EVENT_LINK_CANCEL:
+ /* Received CCBSErase */
+ 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_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ * \internal
+ * \brief CC FSM PTMP 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_ptmp_monitor_activated(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
+{
+ switch (event) {
+ case CC_EVENT_B_FREE:
+ /* Received CCBSBFree */
+ pri_cc_act_pass_up_b_free(ctrl, cc_record);
+ break;
+ case CC_EVENT_REMOTE_USER_FREE:
+ /* Received CCBSRemoteUserFree */
+ pri_cc_act_pass_up_remote_user_free(ctrl, cc_record);
+ break;
+ case CC_EVENT_STOP_ALERTING:
+ pri_cc_act_pass_up_stop_alerting(ctrl, cc_record);
+ break;
+ case CC_EVENT_RECALL:
+ /* The original call parameters have already been set. */
+ pri_cc_act_queue_setup_recall(ctrl, call, cc_record);
+ break;
+ case CC_EVENT_TIMEOUT_T_CCBS2:
+ pri_cc_act_send_cc_deactivate_req(ctrl, cc_record);
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ pri_cc_act_stop_t_ccbs2(ctrl, cc_record);
+ pri_cc_act_set_self_destruct(ctrl, cc_record);
+ cc_record->state = CC_STATE_IDLE;
+ break;
+ case CC_EVENT_LINK_CANCEL:
+ /* Received CCBSErase */
+ pri_cc_act_pass_up_cc_cancel(ctrl, cc_record);
+ pri_cc_act_stop_t_ccbs2(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_send_cc_deactivate_req(ctrl, cc_record);
+ pri_cc_act_stop_t_ccbs2(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.
@@ -2832,6 +3657,17 @@
/* *INDENT-ON* */
};
+/*! CC FSM PTMP monitor state table. */
+static const pri_cc_fsm_state pri_cc_fsm_ptmp_monitor[CC_STATE_NUM] = {
+/* *INDENT-OFF* */
+ [CC_STATE_IDLE] = pri_cc_fsm_ptmp_monitor_idle,
+ [CC_STATE_AVAILABLE] = pri_cc_fsm_ptmp_monitor_avail,
+ [CC_STATE_REQUESTED] = pri_cc_fsm_ptmp_monitor_req,
[... 449 lines stripped ...]
More information about the libpri-commits
mailing list