[libpri-commits] rmudgett: branch group/ccss r1381 - /team/group/ccss/
SVN commits to the libpri project
libpri-commits at lists.digium.com
Wed Dec 9 20:16:45 CST 2009
Author: rmudgett
Date: Wed Dec 9 20:16:42 2009
New Revision: 1381
URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1381
Log:
Added code to respond to CCBSInterrogate/CCNRInterrogate messages.
Modified:
team/group/ccss/pri_cc.c
team/group/ccss/pri_facility.c
team/group/ccss/pri_facility.h
Modified: team/group/ccss/pri_cc.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_cc.c?view=diff&rev=1381&r1=1380&r2=1381
==============================================================================
--- team/group/ccss/pri_cc.c (original)
+++ team/group/ccss/pri_cc.c Wed Dec 9 20:16:42 2009
@@ -301,9 +301,19 @@
cc_record->bc = call->bc;
/*! \todo BUGBUG need more initialization?? */
- /* Insert the new record into the database */
- cc_record->next = ctrl->cc.pool;
- ctrl->cc.pool = cc_record;
+ /*
+ * Append the new record to the end of the list so they are in
+ * cronological order for interrogations.
+ */
+ if (ctrl->cc.pool) {
+ struct pri_cc_record *cur;
+
+ for (cur = ctrl->cc.pool; cur->next; cur = cur->next) {
+ }
+ cur->next = cc_record;
+ } else {
+ ctrl->cc.pool = cc_record;
+ }
return cc_record;
}
@@ -926,6 +936,255 @@
|| q931_facility(ctrl, call)) {
pri_message(ctrl,
"Could not schedule facility message for CCBSStopAlerting.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*!
+ * \internal
+ * \brief Copy the cc information into the ETSI ROSE call-information record.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param call_information ROSE call-information record to fill in.
+ * \param cc_record Call completion record to process event.
+ *
+ * \return Nothing
+ */
+static void q931_copy_call_information_to_etsi_rose(struct pri *ctrl, struct roseEtsiCallInformation *call_information, const struct pri_cc_record *cc_record)
+{
+ q931_copy_address_to_rose(ctrl, &call_information->address_of_b, &cc_record->party_b);
+
+ if (cc_record->saved_ie_contents.length
+ <= sizeof(call_information->q931ie_contents)) {
+ /* Saved BC, HLC, and LLC from initial SETUP */
+ call_information->q931ie.length = cc_record->saved_ie_contents.length;
+ memcpy(call_information->q931ie.contents, cc_record->saved_ie_contents.data,
+ cc_record->saved_ie_contents.length);
+ } else {
+ pri_error(ctrl, "call-information q931 ie contents did not fit.\n");
+ }
+
+ call_information->ccbs_reference = cc_record->ccbs_reference_id;
+
+ q931_copy_subaddress_to_rose(ctrl, &call_information->subaddress_of_a,
+ &cc_record->party_a.subaddress);
+}
+
+/*!
+ * \internal
+ * \brief Encode ETSI PTMP specific CCBSInterrogate/CCNRInterrogate 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 invoke Decoded ROSE invoke message contents.
+ * \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_interrogate_rsp_specific(struct pri *ctrl,
+ unsigned char *pos, unsigned char *end, const struct rose_msg_invoke *invoke,
+ const struct pri_cc_record *cc_record)
+{
+ 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 = invoke->invoke_id;
+ msg.operation = invoke->operation;
+
+ msg.args.etsi.CCBSInterrogate.recall_mode = cc_record->option.recall_mode;
+ msg.args.etsi.CCBSInterrogate.call_details.num_records = 1;
+ q931_copy_call_information_to_etsi_rose(ctrl,
+ &msg.args.etsi.CCBSInterrogate.call_details.list[0], cc_record);
+
+ pos = rose_encode_result(ctrl, pos, end, &msg);
+
+ return pos;
+}
+
+/*!
+ * \internal
+ * \brief Encode ETSI PTMP general CCBSInterrogate/CCNRInterrogate 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 invoke Decoded ROSE invoke message contents.
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *enc_etsi_ptmp_cc_interrogate_rsp_general(struct pri *ctrl,
+ unsigned char *pos, unsigned char *end, const struct rose_msg_invoke *invoke)
+{
+ struct rose_msg_result msg;
+ struct q931_party_number party_a_number;
+ const struct pri_cc_record *cc_record;
+ unsigned char *new_pos;
+ struct pri *master;
+ unsigned idx;
+
+ pos = facility_encode_header(ctrl, pos, end, NULL);
+ if (!pos) {
+ return NULL;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ msg.invoke_id = invoke->invoke_id;
+ msg.operation = invoke->operation;
+
+ master = PRI_MASTER(ctrl);
+ msg.args.etsi.CCBSInterrogate.recall_mode = master->cc.option.recall_mode;
+
+ /* Convert the given party A number. */
+ q931_party_number_init(&party_a_number);
+ if (invoke->args.etsi.CCBSInterrogate.a_party_number.length) {
+ /* The party A number was given. */
+ rose_copy_number_to_q931(ctrl, &party_a_number,
+ &invoke->args.etsi.CCBSInterrogate.a_party_number);
+ }
+
+ /* Build the CallDetails list. */
+ idx = 0;
+ for (cc_record = master->cc.pool; cc_record; cc_record = cc_record->next) {
+ if ((!cc_record->is_ccnr) != (invoke->operation == ROSE_ETSI_CCBSInterrogate)) {
+ /* Record is not for the requested CCBS/CCNR mode. */
+ continue;
+ }
+ if (party_a_number.valid) {
+ /* The party A number was given. */
+ party_a_number.presentation = cc_record->party_a.number.presentation;
+ if (q931_party_number_cmp(&party_a_number, &cc_record->party_a.number)) {
+ continue;
+ }
+ }
+
+ /* Add call information to the CallDetails list. */
+ q931_copy_call_information_to_etsi_rose(ctrl,
+ &msg.args.etsi.CCBSInterrogate.call_details.list[idx], cc_record);
+
+ ++idx;
+ if (ARRAY_LEN(msg.args.etsi.CCBSInterrogate.call_details.list) <= idx) {
+ /* List is full. */
+ break;
+ }
+ }
+ msg.args.etsi.CCBSInterrogate.call_details.num_records = idx;
+
+ new_pos = rose_encode_result(ctrl, pos, end, &msg);
+
+ /* Reduce the CallDetails list until it fits into the given buffer. */
+ while (!new_pos && msg.args.etsi.CCBSInterrogate.call_details.num_records) {
+ --msg.args.etsi.CCBSInterrogate.call_details.num_records;
+ new_pos = rose_encode_result(ctrl, pos, end, &msg);
+ }
+
+ return new_pos;
+}
+
+/*!
+ * \internal
+ * \brief Encode and queue a specific CCBSInterrogate/CCNRInterrogate result message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param call Call leg from which to encode CCBSInterrogate/CCNRInterrogate response.
+ * \param invoke Decoded ROSE invoke message contents.
+ * \param cc_record Call completion record to process event.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int rose_cc_interrogate_rsp_specific(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke, const struct pri_cc_record *cc_record)
+{
+ unsigned char buffer[256];
+ unsigned char *end;
+
+ end =
+ enc_etsi_ptmp_cc_interrogate_rsp_specific(ctrl, buffer, buffer + sizeof(buffer),
+ invoke, cc_record);
+ if (!end) {
+ return -1;
+ }
+
+ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
+}
+
+/*!
+ * \internal
+ * \brief Encode and queue a general CCBSInterrogate/CCNRInterrogate result message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param call Call leg from which to encode CCBSInterrogate/CCNRInterrogate response.
+ * \param invoke Decoded ROSE invoke message contents.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int rose_cc_interrogate_rsp_general(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke)
+{
+ unsigned char buffer[256];
+ unsigned char *end;
+
+ end =
+ enc_etsi_ptmp_cc_interrogate_rsp_general(ctrl, buffer, buffer + sizeof(buffer),
+ invoke);
+ if (!end) {
+ return -1;
+ }
+
+ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
+}
+
+/*!
+ * \brief Respond to the received CCBSInterrogate/CCNRInterrogate 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.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_cc_interrogate_rsp(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke)
+{
+ int encode_result;
+
+ if (!PRI_MASTER(ctrl)->cc_support) {
+ /* Call completion is disabled. */
+ return send_facility_error(ctrl, call, invoke->invoke_id,
+ ROSE_ERROR_Gen_NotSubscribed);
+ }
+
+ if (invoke->args.etsi.CCBSInterrogate.ccbs_reference_present) {
+ struct pri_cc_record *cc_record;
+
+ /* Specific CC request interrogation. */
+ cc_record = pri_cc_find_by_reference(ctrl,
+ invoke->args.etsi.CCBSInterrogate.ccbs_reference);
+ if (!cc_record
+ || ((!cc_record->is_ccnr)
+ == (invoke->operation == ROSE_ETSI_CCBSInterrogate))) {
+ /* Record does not exist or is not for the requested CCBS/CCNR mode. */
+ return send_facility_error(ctrl, call, invoke->invoke_id,
+ ROSE_ERROR_CCBS_InvalidCCBSReference);
+ }
+ encode_result = rose_cc_interrogate_rsp_specific(ctrl, call, invoke, cc_record);
+ } else {
+ /* General CC request interrogation. */
+ encode_result = rose_cc_interrogate_rsp_general(ctrl, call, invoke);
+ }
+
+ if (encode_result || q931_facility(ctrl, call)) {
+ pri_message(ctrl,
+ "Could not schedule facility message for cc-interrogate.\n");
return -1;
}
Modified: team/group/ccss/pri_facility.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_facility.c?view=diff&rev=1381&r1=1380&r2=1381
==============================================================================
--- team/group/ccss/pri_facility.c (original)
+++ team/group/ccss/pri_facility.c Wed Dec 9 20:16:42 2009
@@ -3918,7 +3918,7 @@
pri_cc_event(ctrl, call, cc_record, CC_EVENT_LINK_CANCEL);
break;
case ROSE_ETSI_CCBSInterrogate:
-/* BUGBUG */
+ pri_cc_interrogate_rsp(ctrl, call, invoke);
break;
case ROSE_ETSI_CCBSErase:
break;
@@ -4016,7 +4016,7 @@
pri_cc_event(ctrl, call, cc_record, CC_EVENT_CC_REQUEST);
break;
case ROSE_ETSI_CCNRInterrogate:
-/* BUGBUG */
+ pri_cc_interrogate_rsp(ctrl, call, invoke);
break;
case ROSE_ETSI_CCNR_T_Request:
break;
Modified: team/group/ccss/pri_facility.h
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_facility.h?view=diff&rev=1381&r1=1380&r2=1381
==============================================================================
--- team/group/ccss/pri_facility.h (original)
+++ team/group/ccss/pri_facility.h Wed Dec 9 20:16:42 2009
@@ -228,4 +228,6 @@
void rose_handle_error(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_error *error);
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);
+
#endif /* _PRI_FACILITY_H */
More information about the libpri-commits
mailing list