[libpri-commits] rmudgett: branch group/ccss r1385 - /team/group/ccss/
SVN commits to the libpri project
libpri-commits at lists.digium.com
Sat Dec 12 02:30:26 CST 2009
Author: rmudgett
Date: Sat Dec 12 02:30:21 2009
New Revision: 1385
URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1385
Log:
Commit checkpoint for work in progress.
* Removed pri_cc_deactivate_req()/PRI_SUBCMD_CC_DEACTIVATE_RSP from
public API.
* Added PRI_SUBCMD_CC_STOP_ALERTING to public API.
* Added code to pass the reamaining PTMP CC invoke messages to the PTMP
monitor FSM. (Remains to be written.)
* Other tweaks/fixes to PTMP agent FSM and actions.
* Collected/moved all of the "ERROR: Too many facility subcommands"
messages into q931_alloc_subcommand().
Modified:
team/group/ccss/libpri.h
team/group/ccss/pri.c
team/group/ccss/pri_cc.c
team/group/ccss/pri_facility.c
team/group/ccss/pri_facility.h
team/group/ccss/pri_internal.h
team/group/ccss/q931.c
Modified: team/group/ccss/libpri.h
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/libpri.h?view=diff&rev=1385&r1=1384&r2=1385
==============================================================================
--- team/group/ccss/libpri.h (original)
+++ team/group/ccss/libpri.h Sat Dec 12 02:30:21 2009
@@ -527,7 +527,7 @@
#define PRI_SUBCMD_CC_STATUS 12 /*!< Unsolicited update of CC party A status */
#define PRI_SUBCMD_CC_CALL 13 /*!< Indicate that this call is a CC callback */
#define PRI_SUBCMD_CC_CANCEL 14 /*!< Unsolicited indication that CC is canceled */
-#define PRI_SUBCMD_CC_DEACTIVATE_RSP 15 /*!< CC deactivation request response */
+#define PRI_SUBCMD_CC_STOP_ALERTING 15 /*!< Indicate that someone else has responed to remote user free */
struct pri_subcmd_status_request {
/*!
@@ -584,18 +584,18 @@
* \details
* success(0),
* timeout(1),
- * short_term_denial(2),
- * long_term_denial(3),
- * not_subscribed(4)
+ * error(2),
+ * reject(3)
*/
int status;
/*!
- * \brief Error code that can be converted to a string to further
+ * \brief Failure code that can be converted to a string to further
* explain the non-timeout failure.
- * \note Valid when non-zero.
+ * \note Valid when status is error or reject.
* \note Use pri_facility_error2str() to convert the error_code.
- */
- int error_code;
+ * \note Use pri_facility_reject2str() to convert the reject_code.
+ */
+ int fail_code;
/*!
* \brief TRUE if negotiated to retain CC service if B busy again.
*/
@@ -622,26 +622,6 @@
* busy(1)
*/
int status;
-};
-
-struct pri_subcmd_cc_deactivate_rsp {
- /*! \brief Call-Completion record id */
- long cc_id;
- /*!
- * \brief Status of the requested call-completion deactivation.
- * \details
- * success(0),
- * timeout(1),
- * fail(2)
- */
- int status;
- /*!
- * \brief Error code that can be converted to a string to further
- * explain the non-timeout failure.
- * \note Valid when non-zero.
- * \note Use pri_facility_error2str() to convert the error_code.
- */
- int error_code;
};
struct pri_subcommand {
@@ -664,7 +644,7 @@
struct pri_subcmd_cc_status cc_status;
struct pri_subcmd_cc_id cc_call;
struct pri_subcmd_cc_id cc_cancel;
- struct pri_subcmd_cc_deactivate_rsp cc_deactivate_rsp;
+ struct pri_subcmd_cc_id cc_stop_alerting;
} u;
};
@@ -1023,6 +1003,15 @@
*/
const char *pri_facility_error2str(int facility_error_code);
+/*!
+ * \brief Convert the given facility reject code to a descriptive string.
+ *
+ * \param facility_reject_code Error code to convert to a string.
+ *
+ * \return Descriptive reject string.
+ */
+const char *pri_facility_reject2str(int facility_reject_code);
+
/* Acknowledge a call and place it on the given channel. Set info to non-zero if there
is in-band data available on the channel */
int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info);
@@ -1464,14 +1453,13 @@
long pri_cc_available(struct pri *ctrl, q931_call *call);
int pri_cc_req(struct pri *ctrl, long cc_id, int mode);
-void pri_cc_req_rsp(struct pri *ctrl, long cc_id, int status);
+int pri_cc_req_rsp(struct pri *ctrl, long cc_id, int status);
int pri_cc_remote_user_free(struct pri *ctrl, long cc_id, int is_ccbs_busy);
int 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, int channel, int exclusive);
+int pri_cc_call(struct pri *ctrl, long cc_id, q931_call *call, struct pri_sr *req);
void pri_cc_cancel(struct pri *ctrl, long cc_id);
-int pri_cc_deactivate_req(struct pri *ctrl, long cc_id);
/* Get/Set PRI Timers */
#define PRI_GETSET_TIMERS
Modified: team/group/ccss/pri.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri.c?view=diff&rev=1385&r1=1384&r2=1385
==============================================================================
--- team/group/ccss/pri.c (original)
+++ team/group/ccss/pri.c Sat Dec 12 02:30:21 2009
@@ -1420,8 +1420,6 @@
}
}
-/* BUGBUG add display of active call completion information. */
-
if (buf_size < used) {
pri_message(ctrl,
"pri_dump_info_str(): Produced output exceeded buffer capacity. (Truncated)\n");
Modified: team/group/ccss/pri_cc.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_cc.c?view=diff&rev=1385&r1=1384&r2=1385
==============================================================================
--- team/group/ccss/pri_cc.c (original)
+++ team/group/ccss/pri_cc.c Sat Dec 12 02:30:21 2009
@@ -599,6 +599,10 @@
*/
static int send_ccbs_erase(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, int reason)
{
+/*
+ * XXX May need to add called-party-ie with Party A number in FACILITY message. (CCBSErase)
+ * ETSI EN 300-195-1 Section 5.41 MSN interaction.
+ */
if (rose_ccbs_erase_encode(ctrl, call, cc_record, reason)
|| q931_facility(ctrl, call)) {
pri_message(ctrl,
@@ -607,6 +611,40 @@
}
return 0;
+}
+
+/*!
+ * \internal
+ * \brief Encode ETSI PTMP CCBSStatusRequest result 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.
+ * \param is_free TRUE if the Party A status is available.
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *enc_etsi_ptmp_ccbs_status_request_rsp(struct pri *ctrl,
+ unsigned char *pos, unsigned char *end, struct pri_cc_record *cc_record, int is_free)
+{
+ struct rose_msg_result msg;
+
+ pos = facility_encode_header(ctrl, pos, end, NULL);
+ if (!pos) {
+ return NULL;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ msg.invoke_id = cc_record->response.invoke_id;
+ msg.operation = ROSE_ETSI_CCBSStatusRequest;
+
+ msg.args.etsi.CCBSStatusRequest.free = is_free;
+
+ pos = rose_encode_result(ctrl, pos, end, &msg);
+
+ return pos;
}
/*!
@@ -738,6 +776,10 @@
*/
static int send_ccbs_b_free(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record)
{
+/*
+ * XXX May need to add called-party-ie with Party A number in FACILITY message. (CCBSBFree)
+ * ETSI EN 300-195-1 Section 5.41 MSN interaction.
+ */
if (rose_ccbs_b_free_encode(ctrl, call, cc_record)
|| q931_facility(ctrl, call)) {
pri_message(ctrl,
@@ -826,7 +868,7 @@
}
break;
case PRI_SWITCH_QSIG:
- /* BUGBUG rose_remote_user_free_encode(Q.SIG) not written. */
+ /* \todo BUGBUG rose_remote_user_free_encode(Q.SIG) not written. */
return -1;
default:
return -1;
@@ -851,6 +893,10 @@
*/
static int send_remote_user_free(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record)
{
+/*
+ * XXX May need to add called-party-ie with Party A number in FACILITY message. (CCBSRemoteUserFree)
+ * ETSI EN 300-195-1 Section 5.41 MSN interaction.
+ */
if (rose_remote_user_free_encode(ctrl, call, cc_record, Q931_FACILITY)
|| q931_facility(ctrl, call)) {
pri_message(ctrl,
@@ -1197,6 +1243,50 @@
}
/*!
+ * \brief Respond to the received CCBSRequest/CCNRRequest invoke message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param call Call leg from which the message came.
+ * \param invoke Decoded ROSE invoke message contents.
+ *
+ * \return Nothing
+ */
+void pri_cc_request(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke)
+{
+ struct pri_cc_record *cc_record;
+
+ cc_record = pri_cc_find_by_linkage(ctrl,
+ invoke->args.etsi.CCBSRequest.call_linkage_id);
+ if (!cc_record) {
+ send_facility_error(ctrl, call, invoke->invoke_id,
+ ROSE_ERROR_CCBS_InvalidCallLinkageID);
+ return;
+ }
+ if (cc_record->state != CC_STATE_AVAILABLE) {
+ send_facility_error(ctrl, call, invoke->invoke_id,
+ ROSE_ERROR_CCBS_IsAlreadyActivated);
+ return;
+ }
+ cc_record->ccbs_reference_id = pri_cc_new_reference_id(ctrl);
+ if (cc_record->ccbs_reference_id == CC_PTMP_INVALID_ID) {
+ /* Could not allocate a call reference id. */
+ send_facility_error(ctrl, call, invoke->invoke_id,
+ ROSE_ERROR_CCBS_OutgoingCCBSQueueFull);
+ return;
+ }
+
+ /* Save off data to know how to send back any response. */
+ cc_record->response.signaling = call;
+ cc_record->response.invoke_operation = invoke->operation;
+ cc_record->response.invoke_id = invoke->invoke_id;
+
+ /* Set the requested CC mode. */
+ cc_record->is_ccnr = (invoke->operation == ROSE_ETSI_CCNRRequest) ? 1 : 0;
+
+ pri_cc_event(ctrl, call, cc_record, CC_EVENT_CC_REQUEST);
+}
+
+/*!
* \internal
* \brief Convert the given call completion state to a string.
*
@@ -1270,8 +1360,14 @@
case CC_EVENT_CC_REQUEST_ACCEPT:
str = "CC_EVENT_CC_REQUEST_ACCEPT";
break;
+ case CC_EVENT_CC_REQUEST_FAIL:
+ str = "CC_EVENT_CC_REQUEST_FAIL";
+ break;
case CC_EVENT_REMOTE_USER_FREE:
str = "CC_EVENT_REMOTE_USER_FREE";
+ break;
+ case CC_EVENT_B_FREE:
+ str = "CC_EVENT_B_FREE";
break;
case CC_EVENT_A_STATUS:
str = "CC_EVENT_A_STATUS";
@@ -1727,6 +1823,10 @@
*/
static int send_ccbs_status_request(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record)
{
+/*
+ * XXX May need to add called-party-ie with Party A number in FACILITY message. (CCBSStatusRequest)
+ * ETSI EN 300-195-1 Section 5.41 MSN interaction.
+ */
if (rose_ccbs_status_request(ctrl, call, cc_record)
|| q931_facility(ctrl, call)) {
pri_message(ctrl,
@@ -1880,7 +1980,6 @@
subcmd = q931_alloc_subcommand(ctrl);
if (!subcmd) {
- pri_error(ctrl, "ERROR: Too many facility subcommands\n");
return;
}
@@ -1996,7 +2095,6 @@
subcmd = q931_alloc_subcommand(ctrl);
if (!subcmd) {
- pri_error(ctrl, "ERROR: Too many facility subcommands\n");
return;
}
@@ -2024,7 +2122,6 @@
subcmd = q931_alloc_subcommand(ctrl);
if (!subcmd) {
- pri_error(ctrl, "ERROR: Too many facility subcommands\n");
return;
}
@@ -2050,12 +2147,35 @@
subcmd = q931_alloc_subcommand(ctrl);
if (!subcmd) {
- pri_error(ctrl, "ERROR: Too many facility subcommands\n");
return;
}
subcmd->cmd = PRI_SUBCMD_CC_CANCEL;
subcmd->u.cc_cancel.cc_id = cc_record->record_id;
+}
+
+/*!
+ * \internal
+ * \brief FSM action to pass up CC call 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_call(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_CALL;
+ subcmd->u.cc_call.cc_id = cc_record->record_id;
}
/*!
@@ -2153,7 +2273,6 @@
break;
case CC_EVENT_MSG_DISCONNECT:
pri_cc_act_send_cc_available(ctrl, call, cc_record, Q931_DISCONNECT);
- pri_cc_act_start_t_retention(ctrl, cc_record);
cc_record->state = CC_STATE_AVAILABLE;
break;
case CC_EVENT_CANCEL:
@@ -2179,7 +2298,6 @@
static void pri_cc_fsm_ptmp_agent_avail(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
{
switch (event) {
- case CC_EVENT_MSG_DISCONNECT:
case CC_EVENT_MSG_RELEASE:
case CC_EVENT_MSG_RELEASE_COMPLETE:
pri_cc_act_stop_t_retention(ctrl, cc_record);
@@ -2616,6 +2734,7 @@
cc_record->state = CC_STATE_IDLE;
break;
case CC_EVENT_RECALL:
+ pri_cc_act_pass_up_cc_call(ctrl, cc_record);
pri_cc_act_set_original_call_parameters(ctrl, call, cc_record);
if (cc_record->option.recall_mode == 0 /* globalRecall */) {
pri_cc_act_send_ccbs_stop_alerting(ctrl, cc_record);
@@ -2735,6 +2854,8 @@
*
* \param ctrl D channel controller.
* \param call Q.931 call leg.
+ * (May be NULL if it is supposed to be the signaling connection
+ * for Q.SIG or PTP and it is not established yet.)
* \param cc_record Call completion record to process event.
* \param event Event to process.
*
@@ -2801,6 +2922,9 @@
? "$" : pri_cc_fsm_state_str(cc_record->state));
}
if (cc_record->fsm_complete) {
+ if (call && call->cc.record == cc_record) {
+ call->cc.record = NULL;
+ }
pri_cc_delete_record(ctrl, cc_record);
return 1;
} else {
@@ -2908,6 +3032,9 @@
return -1;
}
+ /* Set the requested CC mode. */
+ cc_record->is_ccnr = mode ? 1 : 0;
+
switch (ctrl->switchtype) {
case PRI_SWITCH_QSIG:
call = q931_new_call(ctrl);
@@ -2915,7 +3042,7 @@
return -1;
}
-/* BUGBUG */
+ /*! \todo BUGBUG pri_cc_req(Q.SIG) not written */
//add_qsigCcRequestArg_facility_ie(ctrl, call, Q931_SETUP, cc_record, mode);
pri_sr_init(&req);
@@ -2931,19 +3058,17 @@
case PRI_SWITCH_EUROISDN_E1:
case PRI_SWITCH_EUROISDN_T1:
if (q931_is_ptmp(ctrl)) {
+ pri_cc_event(ctrl, cc_record->signaling, cc_record, CC_EVENT_CC_REQUEST);
} else {
- }
- return -1;
+ /*! \todo BUGBUG pri_cc_req(PTP) not written */
+ return -1;
+ }
break;
default:
return -1;
}
- cc_record->state = CC_STATE_REQUESTED;
-
return 0;
-
- /*! \todo BUGBUG pri_cc_req() not written */
}
/*!
@@ -3050,10 +3175,23 @@
* \param status success(0)/timeout(1)/
* short_term_denial(2)/long_term_denial(3)/not_subscribed(4)/queue_full(5)
*
- * \return Nothing
- */
-static void rose_cc_req_rsp_ptmp(struct pri *ctrl, struct pri_cc_record *cc_record, int status)
-{
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int rose_cc_req_rsp_ptmp(struct pri *ctrl, struct pri_cc_record *cc_record, int status)
+{
+ int fail;
+
+ switch (cc_record->response.invoke_operation) {
+ case ROSE_ETSI_CCBSRequest:
+ case ROSE_ETSI_CCNRRequest:
+ break;
+ default:
+ /* We no longer know how to send the response. Should not happen. */
+ return -1;
+ }
+
+ fail = 0;
if (status) {
enum rose_error_code code;
@@ -3079,12 +3217,15 @@
CC_EVENT_CANCEL);
} else {
/* Successful CC activation. */
- send_cc_etsi_ptmp_req_rsp(ctrl, cc_record->response.signaling,
+ if (send_cc_etsi_ptmp_req_rsp(ctrl, cc_record->response.signaling,
cc_record->response.invoke_operation, cc_record->response.invoke_id,
- cc_record->option.recall_mode, cc_record->ccbs_reference_id);
+ cc_record->option.recall_mode, cc_record->ccbs_reference_id)) {
+ fail = -1;
+ }
pri_cc_event(ctrl, cc_record->response.signaling, cc_record,
CC_EVENT_CC_REQUEST_ACCEPT);
}
+ return fail;
}
/*!
@@ -3097,33 +3238,41 @@
*
* \note
* If the given status was failure, then the cc_id is no longer valid.
- *
- * \return Nothing
- */
-void pri_cc_req_rsp(struct pri *ctrl, long cc_id, int status)
+ * \note
+ * The caller should cancel CC if error is returned.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_cc_req_rsp(struct pri *ctrl, long cc_id, int status)
{
struct pri_cc_record *cc_record;
+ int fail;
cc_record = pri_cc_find_by_id(ctrl, cc_id);
if (!cc_record) {
- return;
- }
-
+ return -1;
+ }
+
+ fail = -1;
switch (ctrl->switchtype) {
case PRI_SWITCH_QSIG:
+ /*! \todo BUGBUG pri_cc_req_rsp(Q.SIG) not written */
break;
case PRI_SWITCH_EUROISDN_E1:
case PRI_SWITCH_EUROISDN_T1:
if (q931_is_ptmp(ctrl)) {
- rose_cc_req_rsp_ptmp(ctrl, cc_record, status);
+ if (!rose_cc_req_rsp_ptmp(ctrl, cc_record, status)) {
+ fail = 0;
+ }
} else {
+ /*! \todo BUGBUG pri_cc_req_rsp(PTP) not written */
}
break;
default:
break;
}
-
- /*! \todo BUGBUG pri_cc_req_rsp() not written */
+ return fail;
}
/*!
@@ -3153,7 +3302,7 @@
is_ccbs_busy_used = 0;
switch (ctrl->switchtype) {
case PRI_SWITCH_QSIG:
- /*! \todo BUGBUG pri_cc_remote_user_free() not written */
+ /*! \todo BUGBUG pri_cc_remote_user_free(Q.SIG) not written */
break;
case PRI_SWITCH_EUROISDN_E1:
case PRI_SWITCH_EUROISDN_T1:
@@ -3199,6 +3348,7 @@
fail = -1;
switch (ctrl->switchtype) {
case PRI_SWITCH_QSIG:
+ /* Does not apply. */
break;
case PRI_SWITCH_EUROISDN_E1:
case PRI_SWITCH_EUROISDN_T1:
@@ -3215,6 +3365,57 @@
}
/*!
+ * \internal
+ * \brief Encode and queue an CCBSStatusRequest result message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param call Call leg from which to encode CCBSStatusRequest.
+ * \param cc_record Call completion record to process event.
+ * \param is_free TRUE if the Party A status is available.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int rose_ccbs_status_request_rsp(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, int is_free)
+{
+ unsigned char buffer[256];
+ unsigned char *end;
+
+ end =
+ enc_etsi_ptmp_ccbs_status_request_rsp(ctrl, buffer, buffer + sizeof(buffer),
+ cc_record, is_free);
+ if (!end) {
+ return -1;
+ }
+
+ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
+}
+
+/*!
+ * \internal
+ * \brief Encode and send an CCBSStatusRequest result message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param call Call leg from which to encode CCBSStatusRequest.
+ * \param cc_record Call completion record to process event.
+ * \param is_free TRUE if the Party A status is available.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int send_ccbs_status_request_rsp(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, int is_free)
+{
+ if (rose_ccbs_status_request_rsp(ctrl, call, cc_record, is_free)
+ || q931_facility(ctrl, call)) {
+ pri_message(ctrl,
+ "Could not schedule facility message for CCBSStatusRequest result.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*!
* \brief Update the busy status of CC party A.
*
* \param ctrl D channel controller.
@@ -3238,18 +3439,22 @@
switch (ctrl->switchtype) {
case PRI_SWITCH_QSIG:
+ /* Does not apply. */
break;
case PRI_SWITCH_EUROISDN_E1:
case PRI_SWITCH_EUROISDN_T1:
if (q931_is_ptmp(ctrl)) {
- } else {
+ if (cc_record->response.invoke_operation != ROSE_ETSI_CCBSStatusRequest) {
+ /* We no longer know how to send the response. */
+ break;
+ }
+ send_ccbs_status_request_rsp(ctrl, cc_record->signaling, cc_record,
+ status ? 0 /* busy */ : 1 /* free */);
}
break;
default:
break;
}
-
- /*! \todo BUGBUG pri_cc_status_req() not written */
}
/*!
@@ -3275,18 +3480,17 @@
switch (ctrl->switchtype) {
case PRI_SWITCH_QSIG:
+ /*! \todo BUGBUG pri_cc_status(Q.SIG) not written */
break;
case PRI_SWITCH_EUROISDN_E1:
case PRI_SWITCH_EUROISDN_T1:
- if (q931_is_ptmp(ctrl)) {
- } else {
+ if (!q931_is_ptmp(ctrl)) {
+ /*! \todo BUGBUG pri_cc_status(PTP) not written */
}
break;
default:
break;
}
-
- /*! \todo BUGBUG pri_cc_status() not written */
}
/*!
@@ -3295,13 +3499,12 @@
* \param ctrl D channel controller.
* \param cc_id CC record ID to activate.
* \param call Q.931 call leg.
- * \param channel Encoded B channel to use.
- * \param exclusive TRUE if the specified B channel must be used.
+ * \param req SETUP request parameters. Parameters saved by CC will override.
*
* \retval 0 on success.
* \retval -1 on error.
*/
-int pri_cc_call(struct pri *ctrl, long cc_id, q931_call *call, int channel, int exclusive)
+int pri_cc_call(struct pri *ctrl, long cc_id, q931_call *call, struct pri_sr *req)
{
struct pri_cc_record *cc_record;
@@ -3310,21 +3513,27 @@
return -1;
}
- switch (ctrl->switchtype) {
- case PRI_SWITCH_QSIG:
- break;
- case PRI_SWITCH_EUROISDN_E1:
- case PRI_SWITCH_EUROISDN_T1:
- if (q931_is_ptmp(ctrl)) {
- } else {
- }
- break;
- default:
- break;
- }
-
- /*! \todo BUGBUG pri_cc_call() not written */
- return -1;
+ /* Override parameters for sending recall. */
+ req->caller = cc_record->party_a;
+ req->called = cc_record->party_b;
+ req->transmode = cc_record->bc.transcapability;
+ req->userl1 = cc_record->bc.userl1;
+
+ /*
+ * The caller is allowed to send different user-user information.
+ *
+ * It makes no sense for the caller to supply redirecting information
+ * but we'll allow it to pass anyway.
+ */
+ //q931_party_redirecting_init(&req->redirecting);
+
+ /* Add switch specific recall APDU to call. */
+ pri_cc_event(ctrl, call, cc_record, CC_EVENT_RECALL);
+
+ if (q931_setup(ctrl, call, req)) {
+ return -1;
+ }
+ return 0;
}
/*!
@@ -3346,45 +3555,5 @@
pri_cc_event(ctrl, cc_record->signaling, cc_record, CC_EVENT_CANCEL);
}
-/*!
- * \brief Request that the CC be canceled.
- *
- * \param ctrl D channel controller.
- * \param cc_id CC record ID to request deactivation.
- *
- * \note
- * Will always get a PRI_SUBCMD_CC_DEACTIVATE_RSP from libpri.
- * \note
- * Deactivate is used in the party A to party B direction if a response is needed.
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-int pri_cc_deactivate_req(struct pri *ctrl, long cc_id)
-{
- struct pri_cc_record *cc_record;
-
- cc_record = pri_cc_find_by_id(ctrl, cc_id);
- if (!cc_record) {
- return -1;
- }
-
- switch (ctrl->switchtype) {
- case PRI_SWITCH_QSIG:
- break;
- case PRI_SWITCH_EUROISDN_E1:
- case PRI_SWITCH_EUROISDN_T1:
- if (q931_is_ptmp(ctrl)) {
- } else {
- }
- break;
- default:
- break;
- }
-
- /*! \todo BUGBUG pri_cc_deactivate_req() not written */
- return -1;
-}
-
/* ------------------------------------------------------------------- */
/* end pri_cc.c */
Modified: team/group/ccss/pri_facility.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_facility.c?view=diff&rev=1385&r1=1384&r2=1385
==============================================================================
--- team/group/ccss/pri_facility.c (original)
+++ team/group/ccss/pri_facility.c Sat Dec 12 02:30:21 2009
@@ -40,6 +40,11 @@
const char *pri_facility_error2str(int facility_error_code)
{
return rose_error2str(facility_error_code);
+}
+
+const char *pri_facility_reject2str(int facility_reject_code)
+{
+ return rose_reject2str(facility_reject_code);
}
static int redirectingreason_from_q931(struct pri *ctrl, int redirectingreason)
@@ -3545,7 +3550,6 @@
*/
send_facility_error(ctrl, call, invoke->invoke_id,
ROSE_ERROR_Gen_ResourceUnavailable);
- pri_error(ctrl, "ERROR: Too many facility subcommands\n");
break;
}
@@ -3598,7 +3602,6 @@
if (!subcmd) {
send_facility_error(ctrl, call, invoke->invoke_id,
ROSE_ERROR_Gen_ResourceUnavailable);
- pri_error(ctrl, "ERROR: Too many facility subcommands\n");
break;
}
@@ -3751,7 +3754,6 @@
call->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
subcmd = q931_alloc_subcommand(ctrl);
if (!subcmd) {
- pri_error(ctrl, "ERROR: Too many facility subcommands\n");
break;
}
/* Setup redirecting subcommand */
@@ -3839,6 +3841,7 @@
#endif /* Not handled yet */
#if 0 /* Not handled yet */
case ROSE_ETSI_StatusRequest:
+ /*! \todo BUGBUG ROSE_ETSI_StatusRequest not handled */
break;
#endif /* Not handled yet */
case ROSE_ETSI_CallInfoRetain:
@@ -3864,47 +3867,24 @@
cc_record->signaling = PRI_MASTER(ctrl)->dummy_call;
cc_record->call_linkage_id =
invoke->args.etsi.CallInfoRetain.call_linkage_id & 0x7F;
- if (pri_cc_event(ctrl, call, cc_record, CC_EVENT_AVAILABLE)) {
- break;
- }
-
+ call->cc.record = cc_record;
+ pri_cc_event(ctrl, call, cc_record, CC_EVENT_AVAILABLE);
+
+/* BUGBUG move to pri_cc_act_pass_up_cc_available() --v */
subcmd = q931_alloc_subcommand(ctrl);
if (!subcmd) {
- pri_cc_event(ctrl, call, cc_record, CC_EVENT_CANCEL);
- pri_error(ctrl, "ERROR: Too many facility subcommands\n");
- break;
- }
- call->cc.record = cc_record;
+ break;
+ }
subcmd->cmd = PRI_SUBCMD_CC_AVAILABLE;
subcmd->u.cc_available.cc_id = cc_record->record_id;
+/* BUGBUG move to pri_cc_act_pass_up_cc_available() --^ */
break;
case ROSE_ETSI_CCBSRequest:
- cc_record = pri_cc_find_by_linkage(ctrl,
- invoke->args.etsi.CCBSRequest.call_linkage_id);
- if (!cc_record) {
- send_facility_error(ctrl, call, invoke->invoke_id,
- ROSE_ERROR_CCBS_InvalidCallLinkageID);
- break;
- }
- if (cc_record->state != CC_STATE_AVAILABLE) {
- send_facility_error(ctrl, call, invoke->invoke_id,
- ROSE_ERROR_CCBS_IsAlreadyActivated);
- break;
- }
- cc_record->ccbs_reference_id = pri_cc_new_reference_id(ctrl);
- if (cc_record->ccbs_reference_id == CC_PTMP_INVALID_ID) {
- /* Could not allocate a call reference id. */
- send_facility_error(ctrl, call, invoke->invoke_id,
- ROSE_ERROR_CCBS_OutgoingCCBSQueueFull);
- break;
- }
-
- cc_record->response.signaling = call;
- cc_record->response.invoke_operation = invoke->operation;
- cc_record->response.invoke_id = invoke->invoke_id;
- cc_record->is_ccnr = 0;/* ccbs */
- pri_cc_event(ctrl, call, cc_record, CC_EVENT_CC_REQUEST);
+ pri_cc_request(ctrl, call, invoke);
+ break;
+ case ROSE_ETSI_CCNRRequest:
+ pri_cc_request(ctrl, call, invoke);
break;
case ROSE_ETSI_CCBSDeactivate:
cc_record = pri_cc_find_by_reference(ctrl,
@@ -3920,9 +3900,34 @@
case ROSE_ETSI_CCBSInterrogate:
pri_cc_interrogate_rsp(ctrl, call, invoke);
break;
+ case ROSE_ETSI_CCNRInterrogate:
+ pri_cc_interrogate_rsp(ctrl, call, invoke);
+ break;
case ROSE_ETSI_CCBSErase:
+ cc_record = pri_cc_find_by_reference(ctrl,
+ invoke->args.etsi.CCBSErase.ccbs_reference);
+ if (!cc_record) {
+ /*
+ * Ignore any status requests that we do not have a record.
+ * We will not participate in any CC requests that we did
+ * not initiate.
+ */
+ break;
+ }
+ pri_cc_event(ctrl, call, cc_record, CC_EVENT_LINK_CANCEL);
break;
case ROSE_ETSI_CCBSRemoteUserFree:
+ cc_record = pri_cc_find_by_reference(ctrl,
+ invoke->args.etsi.CCBSRemoteUserFree.ccbs_reference);
+ if (!cc_record) {
+ /*
+ * Ignore any status requests that we do not have a record.
+ * We will not participate in any CC requests that we did
+ * not initiate.
+ */
+ break;
+ }
+ pri_cc_event(ctrl, call, cc_record, CC_EVENT_REMOTE_USER_FREE);
break;
case ROSE_ETSI_CCBSCall:
cc_record = pri_cc_find_by_reference(ctrl,
@@ -3934,20 +3939,91 @@
break;
}
+ /* Save off data to know how to send back any response. */
cc_record->response.signaling = call;
cc_record->response.invoke_operation = invoke->operation;
cc_record->response.invoke_id = invoke->invoke_id;
+
pri_cc_event(ctrl, call, cc_record, CC_EVENT_RECALL);
break;
case ROSE_ETSI_CCBSStatusRequest:
+ cc_record = pri_cc_find_by_reference(ctrl,
+ invoke->args.etsi.CCBSStatusRequest.ccbs_reference);
+ if (!cc_record) {
+ /*
+ * Ignore any status requests that we do not have a record.
+ * We will not participate in any CC requests that we did
+ * not initiate.
+ */
+ break;
+ }
+
+ /* Save off data to know how to send back any response. */
+ cc_record->response.signaling = call;
+ cc_record->response.invoke_operation = invoke->operation;
+ cc_record->response.invoke_id = invoke->invoke_id;
+
+ subcmd = q931_alloc_subcommand(ctrl);
+ if (!subcmd) {
+ break;
+ }
+
+ subcmd->cmd = PRI_SUBCMD_CC_STATUS_REQ;
+ subcmd->u.cc_status_req.cc_id = cc_record->record_id;
break;
case ROSE_ETSI_CCBSBFree:
+ cc_record = pri_cc_find_by_reference(ctrl,
+ invoke->args.etsi.CCBSBFree.ccbs_reference);
+ if (!cc_record) {
+ /*
+ * Ignore any status requests that we do not have a record.
+ * We will not participate in any CC requests that we did
+ * not initiate.
+ */
+ break;
+ }
+ pri_cc_event(ctrl, call, cc_record, CC_EVENT_B_FREE);
break;
case ROSE_ETSI_EraseCallLinkageID:
+ cc_record = pri_cc_find_by_linkage(ctrl,
+ invoke->args.etsi.EraseCallLinkageID.call_linkage_id);
+ if (!cc_record) {
+ /*
+ * Ignore any status requests that we do not have a record.
+ * We will not participate in any CC requests that we did
+ * not initiate.
+ */
+ break;
+ }
+ /*
+ * T_RETENTION expired on the network side so we will pretend
+ * that it expired on our side.
+ */
+ pri_cc_event(ctrl, call, cc_record, CC_EVENT_TIMEOUT_T_RETENTION);
break;
case ROSE_ETSI_CCBSStopAlerting:
+ cc_record = pri_cc_find_by_reference(ctrl,
+ invoke->args.etsi.CCBSStopAlerting.ccbs_reference);
+ if (!cc_record) {
+ /*
+ * Ignore any status requests that we do not have a record.
+ * We will not participate in any CC requests that we did
+ * not initiate.
+ */
+ break;
+ }
+
+ subcmd = q931_alloc_subcommand(ctrl);
+ if (!subcmd) {
+ break;
+ }
+
+ subcmd->cmd = PRI_SUBCMD_CC_STOP_ALERTING;
+ subcmd->u.cc_stop_alerting.cc_id = cc_record->record_id;
break;
case ROSE_ETSI_CCBS_T_Request:
+ break;
+ case ROSE_ETSI_CCNR_T_Request:
break;
case ROSE_ETSI_CCBS_T_Call:
break;
@@ -3973,52 +4049,8 @@
if (!cc_record) {
break;
}
- if (pri_cc_event(ctrl, call, cc_record, CC_EVENT_AVAILABLE)) {
- break;
- }
-
- subcmd = q931_alloc_subcommand(ctrl);
- if (!subcmd) {
- pri_cc_event(ctrl, call, cc_record, CC_EVENT_CANCEL);
- pri_error(ctrl, "ERROR: Too many facility subcommands\n");
- break;
- }
call->cc.record = cc_record;
-
- subcmd->cmd = PRI_SUBCMD_CC_AVAILABLE;
- subcmd->u.cc_available.cc_id = cc_record->record_id;
- break;
- case ROSE_ETSI_CCNRRequest:
- cc_record = pri_cc_find_by_linkage(ctrl,
- invoke->args.etsi.CCNRRequest.call_linkage_id);
- if (!cc_record) {
- send_facility_error(ctrl, call, invoke->invoke_id,
- ROSE_ERROR_CCBS_InvalidCallLinkageID);
- break;
- }
- if (cc_record->state != CC_STATE_AVAILABLE) {
- send_facility_error(ctrl, call, invoke->invoke_id,
- ROSE_ERROR_CCBS_IsAlreadyActivated);
- break;
- }
- cc_record->ccbs_reference_id = pri_cc_new_reference_id(ctrl);
- if (cc_record->ccbs_reference_id == CC_PTMP_INVALID_ID) {
- /* Could not allocate a call reference id. */
- send_facility_error(ctrl, call, invoke->invoke_id,
- ROSE_ERROR_CCBS_OutgoingCCBSQueueFull);
- break;
- }
-
- cc_record->response.signaling = call;
- cc_record->response.invoke_operation = invoke->operation;
- cc_record->response.invoke_id = invoke->invoke_id;
- cc_record->is_ccnr = 1;/* ccnr */
- pri_cc_event(ctrl, call, cc_record, CC_EVENT_CC_REQUEST);
- break;
- case ROSE_ETSI_CCNRInterrogate:
- pri_cc_interrogate_rsp(ctrl, call, invoke);
- break;
- case ROSE_ETSI_CCNR_T_Request:
+ pri_cc_event(ctrl, call, cc_record, CC_EVENT_AVAILABLE);
break;
case ROSE_QSIG_CallingName:
/* CallingName is put in remote_id.name */
@@ -4033,7 +4065,6 @@
/* Setup connected line subcommand */
subcmd = q931_alloc_subcommand(ctrl);
if (!subcmd) {
- pri_error(ctrl, "ERROR: Too many facility subcommands\n");
break;
}
subcmd->cmd = PRI_SUBCMD_CONNECTED_LINE;
@@ -4157,7 +4188,6 @@
if (!subcmd) {
send_facility_error(ctrl, call, invoke->invoke_id,
ROSE_ERROR_Gen_ResourceUnavailable);
- pri_error(ctrl, "ERROR: Too many facility subcommands\n");
break;
}
@@ -4351,7 +4381,6 @@
call->redirecting.state = Q931_REDIRECTING_STATE_IDLE;
subcmd = q931_alloc_subcommand(ctrl);
if (!subcmd) {
- pri_error(ctrl, "ERROR: Too many facility subcommands\n");
break;
}
/* Setup redirecting subcommand */
Modified: team/group/ccss/pri_facility.h
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_facility.h?view=diff&rev=1385&r1=1384&r2=1385
==============================================================================
--- team/group/ccss/pri_facility.h (original)
+++ team/group/ccss/pri_facility.h Sat Dec 12 02:30:21 2009
@@ -229,5 +229,6 @@
void rose_handle_reject(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_reject *reject);
int pri_cc_interrogate_rsp(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke);
+void pri_cc_request(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke);
#endif /* _PRI_FACILITY_H */
Modified: team/group/ccss/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_internal.h?view=diff&rev=1385&r1=1384&r2=1385
==============================================================================
--- team/group/ccss/pri_internal.h (original)
+++ team/group/ccss/pri_internal.h Sat Dec 12 02:30:21 2009
@@ -650,8 +650,12 @@
CC_EVENT_CC_REQUEST,
/*! Requesting CC activation accepted. */
CC_EVENT_CC_REQUEST_ACCEPT,
+ /*! Requesting CC activation failed (error/reject received). */
+ CC_EVENT_CC_REQUEST_FAIL,
/*! CC party B is available. */
CC_EVENT_REMOTE_USER_FREE,
+ /*! CC party B is available, party A is busy or CCBS busy. */
+ CC_EVENT_B_FREE,
/*! CC poll/prompt for party A status. */
CC_EVENT_A_STATUS,
/*! CC party A is free/available for recall. */
Modified: team/group/ccss/q931.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/q931.c?view=diff&rev=1385&r1=1384&r2=1385
==============================================================================
--- team/group/ccss/q931.c (original)
+++ team/group/ccss/q931.c Sat Dec 12 02:30:21 2009
@@ -900,6 +900,7 @@
return &ctrl->subcmds.subcmd[ctrl->subcmds.counter_subcmd++];
}
+ pri_error(ctrl, "ERROR: Too many facility subcommands\n");
return NULL;
}
More information about the libpri-commits
mailing list