[libpri-commits] rmudgett: branch group/ccss r1344 - /team/group/ccss/

SVN commits to the libpri project libpri-commits at lists.digium.com
Fri Nov 20 11:28:19 CST 2009


Author: rmudgett
Date: Fri Nov 20 11:28:16 2009
New Revision: 1344

URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1344
Log:
Commit checkpoint for work in progress.

*  Rearange code to make some pri_facility.c functions available to
pri_cc.c.
*  Some progress on PTMP call completion.
*  Make q931_encode_channel() handle the cis_call flag like the held_call
flag.  Asterisk will need to deal with PRI events coming in with the
cis_call flag set in the channel parameter.  Asterisk should generally
treat subcmds from these events as coming in without a call.
*  q931_fill_facility_event() now sets the PRI_EVENT_FACILITY call
parameter to NULL if the call reference is the dummy call reference.

Modified:
    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/pri.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri.c?view=diff&rev=1344&r1=1343&r2=1344
==============================================================================
--- team/group/ccss/pri.c (original)
+++ team/group/ccss/pri.c Fri Nov 20 11:28:16 2009
@@ -40,8 +40,6 @@
 #include "libpri.h"
 #include "pri_internal.h"
 #include "pri_facility.h"
-#include "pri_q921.h"
-#include "pri_q931.h"
 
 #define PRI_BIT(a_bit)		(1UL << (a_bit))
 #define PRI_ALL_SWITCHES	0xFFFFFFFF

Modified: team/group/ccss/pri_cc.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_cc.c?view=diff&rev=1344&r1=1343&r2=1344
==============================================================================
--- team/group/ccss/pri_cc.c (original)
+++ team/group/ccss/pri_cc.c Fri Nov 20 11:28:16 2009
@@ -35,17 +35,14 @@
 #include "compat.h"
 #include "libpri.h"
 #include "pri_internal.h"
-#include "pri_q921.h"
-#include "pri_q931.h"
+#include "pri_facility.h"
 
 #include <stdlib.h>
 
 
 /* ------------------------------------------------------------------- */
 
-#if defined(BUGBUG_NOT_USED_YET)
-/*!
- * \internal
+/*!
  * \brief Find a cc_record by the PTMP reference_id.
  *
  * \param ctrl D channel controller.
@@ -54,7 +51,7 @@
  * \retval cc_record on success.
  * \retval NULL on error.
  */
-static struct pri_cc_record *pri_cc_find_by_reference(struct pri *ctrl, unsigned reference_id)
+struct pri_cc_record *pri_cc_find_by_reference(struct pri *ctrl, unsigned reference_id)
 {
 	struct pri_cc_record *cc_record;
 
@@ -68,10 +65,8 @@
 
 	return cc_record;
 }
-#endif
-
-/*!
- * \internal
+
+/*!
  * \brief Find a cc_record by the PTMP linkage_id.
  *
  * \param ctrl D channel controller.
@@ -80,7 +75,7 @@
  * \retval cc_record on success.
  * \retval NULL on error.
  */
-static struct pri_cc_record *pri_cc_find_by_linkage(struct pri *ctrl, unsigned linkage_id)
+struct pri_cc_record *pri_cc_find_by_linkage(struct pri *ctrl, unsigned linkage_id)
 {
 	struct pri_cc_record *cc_record;
 
@@ -120,19 +115,17 @@
 	return cc_record;
 }
 
-#if defined(BUGBUG_NOT_USED_YET)
-/*!
- * \internal
+/*!
  * \brief Find a cc_record by an incoming call addressing data.
  *
  * \param ctrl D channel controller.
- * \param party_a Party A address. 
+ * \param party_a Party A address.
  * \param party_b Party B address.
  *
  * \retval cc_record on success.
  * \retval NULL on error.
  */
-static struct pri_cc_record *pri_cc_find_by_addressing(struct pri *ctrl, const struct q931_party_address *party_a, const struct q931_party_address *party_b)
+struct pri_cc_record *pri_cc_find_by_addressing(struct pri *ctrl, const struct q931_party_address *party_a, const struct q931_party_address *party_b)
 {
 	struct pri_cc_record *cc_record;
 
@@ -149,19 +142,16 @@
 
 	/*! \todo BUGBUG pri_cc_find_by_addressing() not written */
 }
-#endif
-
-#if defined(BUGBUG_NOT_USED_YET)
-/*!
- * \internal
+
+/*!
  * \brief Allocate a new cc_record reference id.
  *
  * \param ctrl D channel controller.
  *
  * \retval reference_id on success.
- * \retval -1 on error.
- */
-static int pri_cc_new_reference_id(struct pri *ctrl)
+ * \retval CC_PTMP_INVALID_ID on error.
+ */
+int pri_cc_new_reference_id(struct pri *ctrl)
 {
 	long reference_id;
 	long first_id;
@@ -176,14 +166,13 @@
 		if (reference_id == first_id) {
 			/* We probably have a resource leak. */
 			pri_error(ctrl, "PTMP call completion reference id exhaustion!\n");
-			reference_id = -1;
+			reference_id = CC_PTMP_INVALID_ID;
 			break;
 		}
 	}
 
 	return reference_id;
 }
-#endif
 
 /*!
  * \internal
@@ -192,7 +181,7 @@
  * \param ctrl D channel controller.
  *
  * \retval linkage_id on success.
- * \retval -1 on error.
+ * \retval CC_PTMP_INVALID_ID on error.
  */
 static int pri_cc_new_linkage_id(struct pri *ctrl)
 {
@@ -209,7 +198,7 @@
 		if (linkage_id == first_id) {
 			/* We probably have a resource leak. */
 			pri_error(ctrl, "PTMP call completion linkage id exhaustion!\n");
-			linkage_id = -1;
+			linkage_id = CC_PTMP_INVALID_ID;
 			break;
 		}
 	}
@@ -318,6 +307,110 @@
 }
 
 /*!
+ * \internal
+ * \brief Encode ETSI PTP call completion event operation 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 operation PTP call completion event operation to encode.
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *enc_etsi_ptp_cc_operation(struct pri *ctrl, unsigned char *pos,
+	unsigned char *end, enum rose_operation operation)
+{
+	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 = operation;
+
+	pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+	return pos;
+}
+
+/*!
+ * \internal
+ * \brief Encode ETSI PTMP call completion available 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 call Call leg from which to encode message.
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *enc_etsi_ptmp_cc_available(struct pri *ctrl, unsigned char *pos,
+	unsigned char *end, q931_call *call)
+{
+	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_CallInfoRetain;
+
+	msg.args.etsi.CallInfoRetain.call_linkage_id = call->cc.record->call_linkage_id;
+
+	pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+	return pos;
+}
+
+/*!
+ * \brief Encode and queue a cc-available message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param call Call leg from which to encode call completion available.
+ * \param msgtype Q.931 message type to put facility ie in.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int rose_cc_available_encode(struct pri *ctrl, q931_call *call, int msgtype)
+{
+	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_available(ctrl, buffer, buffer + sizeof(buffer), call);
+		} else {
+			end =
+				enc_etsi_ptp_cc_operation(ctrl, buffer, buffer + sizeof(buffer),
+					ROSE_ETSI_CCBS_T_Available);
+		}
+		break;
+	case PRI_SWITCH_QSIG:
+		/* Q.SIG does not have a cc-available type message. */
+		return 0;
+	default:
+		return -1;
+	}
+	if (!end) {
+		return -1;
+	}
+
+	return pri_call_apdu_queue(call, msgtype, buffer, end - buffer, NULL);
+}
+
+/*!
  * \brief Send an event from the upper layer to the cc state machine.
  *
  * \param ctrl D channel controller.
@@ -428,7 +521,7 @@
 			int linkage_id;
 
 			linkage_id = pri_cc_new_linkage_id(ctrl);
-			if (linkage_id < 0) {
+			if (linkage_id == CC_PTMP_INVALID_ID) {
 				break;
 			}
 			cc_record = pri_cc_new_record(ctrl, call);
@@ -522,23 +615,171 @@
 }
 
 /*!
+ * \internal
+ * \brief Encode a PTMP cc-request reply 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 operation CCBS/CCNR operation code.
+ * \param invoke_id Invoke id to put in error message response.
+ * \param recall_mode Configured PTMP recall mode.
+ * \param reference_id Active CC reference id.
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *enc_cc_etsi_ptmp_req_rsp(struct pri *ctrl, unsigned char *pos,
+	unsigned char *end, enum rose_operation operation, int invoke_id, int recall_mode,
+	int reference_id)
+{
+	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_id;
+	msg.operation = operation;
+
+	/* CCBS/CCNR reply */
+	msg.args.etsi.CCBSRequest.recall_mode = recall_mode;
+	msg.args.etsi.CCBSRequest.ccbs_reference = reference_id;
+
+	pos = rose_encode_result(ctrl, pos, end, &msg);
+
+	return pos;
+}
+
+/*!
+ * \internal
+ * \brief Encode and queue PTMP a cc-request reply message.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param msgtype Q.931 message type to put facility ie in.
+ * \param operation CCBS/CCNR operation code.
+ * \param invoke_id Invoke id to put in error message response.
+ * \param recall_mode Configured PTMP recall mode.
+ * \param reference_id Active CC reference id.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int rose_cc_etsi_ptmp_req_rsp_encode(struct pri *ctrl, q931_call *call, int msgtype, enum rose_operation operation, int invoke_id, int recall_mode, int reference_id)
+{
+	unsigned char buffer[256];
+	unsigned char *end;
+
+	end = enc_cc_etsi_ptmp_req_rsp(ctrl, buffer, buffer + sizeof(buffer), operation,
+		invoke_id, recall_mode, reference_id);
+	if (!end) {
+		return -1;
+	}
+
+	return pri_call_apdu_queue(call, msgtype, buffer, end - buffer, NULL);
+}
+
+/*!
+ * \internal
+ * \brief Send the CC activation request result PTMP.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ * \param operation CCBS/CCNR operation code.
+ * \param invoke_id Invoke id to put in error message response.
+ * \param recall_mode Configured PTMP recall mode.
+ * \param reference_id Active CC reference id.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int send_cc_etsi_ptmp_req_rsp(struct pri *ctrl, q931_call *call, enum rose_operation operation, int invoke_id, int recall_mode, int reference_id)
+{
+	if (rose_cc_etsi_ptmp_req_rsp_encode(ctrl, call, Q931_FACILITY, operation, invoke_id,
+		recall_mode, reference_id)
+		|| q931_facility(ctrl, call)) {
+		pri_message(ctrl,
+			"Could not schedule facility message for CC request result message.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+/*!
+ * \internal
+ * \brief Response to an incoming CC activation request PTMP.
+ *
+ * \param ctrl D channel controller.
+ * \param cc_record Call completion record to process event.
+ * \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)
+{
+	if (status) {
+		enum rose_error_code code;
+
+		switch (status) {
+		default:
+		case 1:/* timeout */
+		case 2:/* short_term_denial */
+			code = ROSE_ERROR_CCBS_ShortTermDenial;
+			break;
+		case 3:/* long_term_denial */
+			code = ROSE_ERROR_CCBS_LongTermDenial;
+			break;
+		case 4:/* not_subscribed */
+			code = ROSE_ERROR_Gen_NotSubscribed;
+			break;
+		case 5:/* queue_full */
+			code = ROSE_ERROR_CCBS_OutgoingCCBSQueueFull;
+			break;
+		}
+		send_facility_error(ctrl, cc_record->response.signaling,
+			cc_record->response.invoke_id, code);
+		cc_record->state = CC_STATE_AVAILABLE;
+		cc_record->ccbs_reference_id = CC_PTMP_INVALID_ID;
+	} else {
+		/* Successful CC activation. */
+		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->state = CC_STATE_ACTIVATED;
+	}
+}
+
+/*!
  * \brief Response to an incoming CC activation request.
  *
  * \param ctrl D channel controller.
  * \param cc_id CC record ID to activate.
  * \param status success(0)/timeout(1)/
- *		short_term_denial(2)/long_term_denial(3)/not_subscribed(4)
+ *		short_term_denial(2)/long_term_denial(3)/not_subscribed(4)/queue_full(5)
  *
  * \return Nothing
  */
 void pri_cc_req_rsp(struct pri *ctrl, long cc_id, int status)
 {
+	struct pri_cc_record *cc_record;
+
+	cc_record = pri_cc_find_by_id(ctrl, cc_id);
+	if (!cc_record) {
+		return;
+	}
+
 	switch (ctrl->switchtype) {
 	case PRI_SWITCH_QSIG:
 		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);
 		} else {
 		}
 		break;

Modified: team/group/ccss/pri_facility.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_facility.c?view=diff&rev=1344&r1=1343&r2=1344
==============================================================================
--- team/group/ccss/pri_facility.c (original)
+++ team/group/ccss/pri_facility.c Fri Nov 20 11:28:16 2009
@@ -30,10 +30,7 @@
 #include "compat.h"
 #include "libpri.h"
 #include "pri_internal.h"
-#include "pri_q921.h"
-#include "pri_q931.h"
 #include "pri_facility.h"
-#include "rose.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -43,12 +40,6 @@
 const char *pri_facility_error2str(int facility_error_code)
 {
 	return rose_error2str(facility_error_code);
-}
-
-static short get_invokeid(struct pri *ctrl)
-{
-	ctrl = PRI_MASTER(ctrl);
-	return ++ctrl->last_invoke;
 }
 
 static int redirectingreason_from_q931(struct pri *ctrl, int redirectingreason)
@@ -503,7 +494,6 @@
 }
 
 /*!
- * \internal
  * \brief Copy the given rose party number to the q931_party_number
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -514,8 +504,8 @@
  *
  * \return Nothing
  */
-static void rose_copy_number_to_q931(struct pri *ctrl,
-	struct q931_party_number *q931_number, const struct rosePartyNumber *rose_number)
+void rose_copy_number_to_q931(struct pri *ctrl, struct q931_party_number *q931_number,
+	const struct rosePartyNumber *rose_number)
 {
 	//q931_party_number_init(q931_number);
 	libpri_copy_string(q931_number->str, (char *) rose_number->str,
@@ -526,7 +516,6 @@
 }
 
 /*!
- * \internal
  * \brief Copy the given rose subaddress to the q931_party_subaddress.
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -537,7 +526,7 @@
  *
  * \return Nothing
  */
-static void rose_copy_subaddress_to_q931(struct pri *ctrl,
+void rose_copy_subaddress_to_q931(struct pri *ctrl,
 	struct q931_party_subaddress *q931_subaddress,
 	const struct rosePartySubaddress *rose_subaddress)
 {
@@ -577,7 +566,6 @@
 }
 
 /*!
- * \internal
  * \brief Copy the given rose address to the q931_party_id address.
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -588,8 +576,8 @@
  *
  * \return Nothing
  */
-static void rose_copy_address_to_q931(struct pri *ctrl,
-	struct q931_party_id *q931_address, const struct roseAddress *rose_address)
+void rose_copy_address_to_q931(struct pri *ctrl, struct q931_party_id *q931_address,
+	const struct roseAddress *rose_address)
 {
 	rose_copy_number_to_q931(ctrl, &q931_address->number, &rose_address->number);
 	rose_copy_subaddress_to_q931(ctrl, &q931_address->subaddress,
@@ -597,7 +585,6 @@
 }
 
 /*!
- * \internal
  * \brief Copy the given rose presented screened party number to the q931_party_number
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -606,7 +593,7 @@
  *
  * \return Nothing
  */
-static void rose_copy_presented_number_screened_to_q931(struct pri *ctrl,
+void rose_copy_presented_number_screened_to_q931(struct pri *ctrl,
 	struct q931_party_number *q931_number,
 	const struct rosePresentedNumberScreened *rose_presented)
 {
@@ -628,7 +615,6 @@
 }
 
 /*!
- * \internal
  * \brief Copy the given rose presented unscreened party number to the q931_party_number
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -637,7 +623,7 @@
  *
  * \return Nothing
  */
-static void rose_copy_presented_number_unscreened_to_q931(struct pri *ctrl,
+void rose_copy_presented_number_unscreened_to_q931(struct pri *ctrl,
 	struct q931_party_number *q931_number,
 	const struct rosePresentedNumberUnscreened *rose_presented)
 {
@@ -656,7 +642,6 @@
 }
 
 /*!
- * \internal
  * \brief Copy the given rose presented screened party address to the q931_party_number
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -665,7 +650,7 @@
  *
  * \return Nothing
  */
-static void rose_copy_presented_address_screened_to_q931(struct pri *ctrl,
+void rose_copy_presented_address_screened_to_q931(struct pri *ctrl,
 	struct q931_party_id *q931_address,
 	const struct rosePresentedAddressScreened *rose_presented)
 {
@@ -691,7 +676,6 @@
 }
 
 /*!
- * \internal
  * \brief Copy the given rose party name to the q931_party_name
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -700,8 +684,8 @@
  *
  * \return Nothing
  */
-static void rose_copy_name_to_q931(struct pri *ctrl,
-	struct q931_party_name *qsig_name, const struct roseQsigName *rose_name)
+void rose_copy_name_to_q931(struct pri *ctrl, struct q931_party_name *qsig_name,
+	const struct roseQsigName *rose_name)
 {
 	//q931_party_name_init(qsig_name);
 	qsig_name->valid = 1;
@@ -712,7 +696,6 @@
 }
 
 /*!
- * \internal
  * \brief Copy the given q931_party_number to the rose party number
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -721,8 +704,8 @@
  *
  * \return Nothing
  */
-static void q931_copy_number_to_rose(struct pri *ctrl,
-	struct rosePartyNumber *rose_number, const struct q931_party_number *q931_number)
+void q931_copy_number_to_rose(struct pri *ctrl, struct rosePartyNumber *rose_number,
+	const struct q931_party_number *q931_number)
 {
 	rose_number->plan = numbering_plan_from_q931(ctrl, q931_number->plan);
 	rose_number->ton = typeofnumber_from_q931(ctrl, q931_number->plan);
@@ -733,7 +716,6 @@
 }
 
 /*!
- * \internal
  * \brief Copy the given q931_party_subaddress to the rose subaddress.
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -742,7 +724,7 @@
  *
  * \return Nothing
  */
-static void q931_copy_subaddress_to_rose(struct pri *ctrl,
+void q931_copy_subaddress_to_rose(struct pri *ctrl,
 	struct rosePartySubaddress *rose_subaddress,
 	const struct q931_party_subaddress *q931_subaddress)
 {
@@ -784,7 +766,6 @@
 }
 
 /*!
- * \internal
  * \brief Copy the given q931_party_id address to the rose address.
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -793,7 +774,7 @@
  *
  * \return Nothing
  */
-static void q931_copy_address_to_rose(struct pri *ctrl, struct roseAddress *rose_address,
+void q931_copy_address_to_rose(struct pri *ctrl, struct roseAddress *rose_address,
 	const struct q931_party_id *q931_address)
 {
 	q931_copy_number_to_rose(ctrl, &rose_address->number, &q931_address->number);
@@ -802,7 +783,6 @@
 }
 
 /*!
- * \internal
  * \brief Copy the given q931_party_number to the rose presented screened party number
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -811,7 +791,7 @@
  *
  * \return Nothing
  */
-static void q931_copy_presented_number_screened_to_rose(struct pri *ctrl,
+void q931_copy_presented_number_screened_to_rose(struct pri *ctrl,
 	struct rosePresentedNumberScreened *rose_presented,
 	const struct q931_party_number *q931_number)
 {
@@ -827,7 +807,6 @@
 }
 
 /*!
- * \internal
  * \brief Copy the given q931_party_number to the rose presented unscreened party number
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -836,7 +815,7 @@
  *
  * \return Nothing
  */
-static void q931_copy_presented_number_unscreened_to_rose(struct pri *ctrl,
+void q931_copy_presented_number_unscreened_to_rose(struct pri *ctrl,
 	struct rosePresentedNumberUnscreened *rose_presented,
 	const struct q931_party_number *q931_number)
 {
@@ -849,9 +828,7 @@
 	}
 }
 
-#if 0	/* In case it is needed in the future */
-/*!
- * \internal
+/*!
  * \brief Copy the given q931_party_number to the rose presented screened party address
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -860,7 +837,7 @@
  *
  * \return Nothing
  */
-static void q931_copy_presented_address_screened_to_rose(struct pri *ctrl,
+void q931_copy_presented_address_screened_to_rose(struct pri *ctrl,
 	struct rosePresentedAddressScreened *rose_presented,
 	const struct q931_party_id *q931_address)
 {
@@ -878,10 +855,8 @@
 		rose_presented->presentation = 2;/* numberNotAvailableDueToInterworking */
 	}
 }
-#endif	/* In case it is needed in the future */
-
-/*!
- * \internal
+
+/*!
  * \brief Copy the given q931_party_name to the rose party name
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -890,8 +865,8 @@
  *
  * \return Nothing
  */
-static void q931_copy_name_to_rose(struct pri *ctrl,
-	struct roseQsigName *rose_name, const struct q931_party_name *qsig_name)
+void q931_copy_name_to_rose(struct pri *ctrl, struct roseQsigName *rose_name,
+	const struct q931_party_name *qsig_name)
 {
 	if (qsig_name->valid) {
 		rose_name->presentation = qsig_name_presentation_from_q931(ctrl,
@@ -2991,18 +2966,18 @@
 }
 
 /*!
- * \internal
  * \brief Encode and queue a plain facility error code.
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
  * \param call Call leg from which to encode error message response.
+ * \param msgtype Q.931 message type to put facility ie in.
  * \param invoke_id Invoke id to put in error message response.
  * \param code Error code to put in error message response.
  *
  * \retval 0 on success.
  * \retval -1 on error.
  */
-static int rose_facility_error_encode(struct pri *ctrl, q931_call *call, int invoke_id,
+int rose_error_msg_encode(struct pri *ctrl, q931_call *call, int msgtype, int invoke_id,
 	enum rose_error_code code)
 {
 	unsigned char buffer[256];
@@ -3025,7 +3000,7 @@
 		return -1;
 	}
 
-	return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
+	return pri_call_apdu_queue(call, msgtype, buffer, end - buffer, NULL);
 }
 
 /*!
@@ -3039,10 +3014,10 @@
  * \retval 0 on success.
  * \retval -1 on error.
  */
-static int send_facility_error(struct pri *ctrl, q931_call *call, int invoke_id,
+int send_facility_error(struct pri *ctrl, q931_call *call, int invoke_id,
 	enum rose_error_code code)
 {
-	if (rose_facility_error_encode(ctrl, call, invoke_id, code)
+	if (rose_error_msg_encode(ctrl, call, Q931_FACILITY, invoke_id, code)
 		|| q931_facility(ctrl, call)) {
 		pri_message(ctrl,
 			"Could not schedule facility message for error message.\n");
@@ -3124,7 +3099,6 @@
 }
 
 /*!
- * \internal
  * \brief Encode and queue a plain ROSE result ok.
  *
  * \param ctrl D channel controller for diagnostic messages or global options.
@@ -3135,7 +3109,7 @@
  * \retval 0 on success.
  * \retval -1 on error.
  */
-static int rose_result_ok_encode(struct pri *ctrl, q931_call *call, int msgtype, int invoke_id)
+int rose_result_ok_encode(struct pri *ctrl, q931_call *call, int msgtype, int invoke_id)
 {
 	unsigned char buffer[256];
 	unsigned char *end;
@@ -3170,7 +3144,7 @@
  * \retval 0 on success.
  * \retval -1 on error.
  */
-static int send_facility_result_ok(struct pri *ctrl, q931_call *call, int invoke_id)
+int send_facility_result_ok(struct pri *ctrl, q931_call *call, int invoke_id)
 {
 	if (rose_result_ok_encode(ctrl, call, Q931_FACILITY, invoke_id)
 		|| q931_facility(ctrl, call)) {
@@ -3223,111 +3197,6 @@
 		break;
 	}
 	return send_facility_error(ctrl, call, invoke_id, rose_err);
-}
-
-/*!
- * \internal
- * \brief Encode ETSI PTP call completion event operation 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 call Call leg from which to encode message.
- * \param operation PTP call completion event operation to encode.
- *
- * \retval Start of the next ASN.1 component to encode on success.
- * \retval NULL on error.
- */
-static unsigned char *enc_etsi_ptp_cc_operation(struct pri *ctrl, unsigned char *pos,
-	unsigned char *end, q931_call *call, enum rose_operation operation)
-{
-	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 = operation;
-
-	pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-	return pos;
-}
-
-/*!
- * \internal
- * \brief Encode ETSI PTMP call completion available 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 call Call leg from which to encode message.
- *
- * \retval Start of the next ASN.1 component to encode on success.
- * \retval NULL on error.
- */
-static unsigned char *enc_etsi_ptmp_cc_available(struct pri *ctrl, unsigned char *pos,
-	unsigned char *end, q931_call *call)
-{
-	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_CallInfoRetain;
-
-	msg.args.etsi.CallInfoRetain.call_linkage_id = call->cc.record->call_linkage_id;
-
-	pos = rose_encode_invoke(ctrl, pos, end, &msg);
-
-	return pos;
-}
-
-/*!
- * \brief Encode and queue a cc-available message.
- *
- * \param ctrl D channel controller for diagnostic messages or global options.
- * \param call Call leg from which to encode call completion available.
- * \param msgtype Q.931 message type to put facility ie in.
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-int rose_cc_available_encode(struct pri *ctrl, q931_call *call, int msgtype)
-{
-	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_available(ctrl, buffer, buffer + sizeof(buffer), call);
-		} else {
-			end =
-				enc_etsi_ptp_cc_operation(ctrl, buffer, buffer + sizeof(buffer), call,
-					ROSE_ETSI_CCBS_T_Available);
-		}
-		break;
-	case PRI_SWITCH_QSIG:
-		/* Q.SIG does not have a cc-available type message. */
-		return 0;
-	default:
-		return -1;
-	}
-	if (!end) {
-		return -1;
-	}
-
-	return pri_call_apdu_queue(call, msgtype, buffer, end - buffer, NULL);
 }
 
 /*!
@@ -3891,6 +3760,39 @@
 		subcmd->u.cc_available.cc_id = cc_record->record_id;
 		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->state = CC_STATE_REQUESTED;
+		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) {
+			pri_error(ctrl, "ERROR: Too many facility subcommands\n");
+			break;
+		}
+
+		subcmd->cmd = PRI_SUBCMD_CC_REQ;
+		subcmd->u.cc_request.cc_id =  cc_record->record_id;
+		subcmd->u.cc_request.mode = 0;/* ccbs */
 		break;
 	case ROSE_ETSI_CCBSDeactivate:
 		break;
@@ -3950,6 +3852,39 @@
 		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->state = CC_STATE_REQUESTED;
+		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) {
+			pri_error(ctrl, "ERROR: Too many facility subcommands\n");
+			break;
+		}
+
+		subcmd->cmd = PRI_SUBCMD_CC_REQ;
+		subcmd->u.cc_request.cc_id =  cc_record->record_id;
+		subcmd->u.cc_request.mode = 1;/* ccnr */
 		break;
 	case ROSE_ETSI_CCNRInterrogate:
 		break;

Modified: team/group/ccss/pri_facility.h
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_facility.h?view=diff&rev=1344&r1=1343&r2=1344
==============================================================================
--- team/group/ccss/pri_facility.h (original)
+++ team/group/ccss/pri_facility.h Fri Nov 20 11:28:16 2009
@@ -30,13 +30,7 @@
 #ifndef _PRI_FACILITY_H
 #define _PRI_FACILITY_H
 #include "pri_q931.h"
-
-/* Forward declare some structs */
-struct fac_extension_header;
-struct rose_msg_invoke;
-struct rose_msg_result;
-struct rose_msg_error;
-struct rose_msg_reject;
+#include "rose.h"
 
 /* Protocol Profile field */
 #define Q932_PROTOCOL_MASK			0x1F
@@ -173,6 +167,27 @@
 	unsigned char apdu[255];
 };
 
+void rose_copy_number_to_q931(struct pri *ctrl, struct q931_party_number *q931_number, const struct rosePartyNumber *rose_number);
+void rose_copy_subaddress_to_q931(struct pri *ctrl, struct q931_party_subaddress *q931_subaddress, const struct rosePartySubaddress *rose_subaddress);
+void rose_copy_address_to_q931(struct pri *ctrl, struct q931_party_id *q931_address, const struct roseAddress *rose_address);
+void rose_copy_presented_number_screened_to_q931(struct pri *ctrl, struct q931_party_number *q931_number, const struct rosePresentedNumberScreened *rose_presented);
+void rose_copy_presented_number_unscreened_to_q931(struct pri *ctrl, struct q931_party_number *q931_number, const struct rosePresentedNumberUnscreened *rose_presented);
+void rose_copy_presented_address_screened_to_q931(struct pri *ctrl, struct q931_party_id *q931_address, const struct rosePresentedAddressScreened *rose_presented);
+void rose_copy_name_to_q931(struct pri *ctrl, struct q931_party_name *qsig_name, const struct roseQsigName *rose_name);
+
+void q931_copy_number_to_rose(struct pri *ctrl, struct rosePartyNumber *rose_number, const struct q931_party_number *q931_number);
+void q931_copy_subaddress_to_rose(struct pri *ctrl, struct rosePartySubaddress *rose_subaddress, const struct q931_party_subaddress *q931_subaddress);
+void q931_copy_address_to_rose(struct pri *ctrl, struct roseAddress *rose_address, const struct q931_party_id *q931_address);
+void q931_copy_presented_number_screened_to_rose(struct pri *ctrl, struct rosePresentedNumberScreened *rose_presented, const struct q931_party_number *q931_number);
+void q931_copy_presented_number_unscreened_to_rose(struct pri *ctrl, struct rosePresentedNumberUnscreened *rose_presented, const struct q931_party_number *q931_number);
+void q931_copy_presented_address_screened_to_rose(struct pri *ctrl, struct rosePresentedAddressScreened *rose_presented, const struct q931_party_id *q931_address);
+void q931_copy_name_to_rose(struct pri *ctrl, struct roseQsigName *rose_name, const struct q931_party_name *qsig_name);
+
+int rose_error_msg_encode(struct pri *ctrl, q931_call *call, int msgtype, int invoke_id, enum rose_error_code code);
+int send_facility_error(struct pri *ctrl, q931_call *call, int invoke_id, enum rose_error_code code);
+int rose_result_ok_encode(struct pri *ctrl, q931_call *call, int msgtype, int invoke_id);
+int send_facility_result_ok(struct pri *ctrl, q931_call *call, int invoke_id);
+
 /* Queues an MWI apdu on a the given call */
 int mwi_message_send(struct pri *pri, q931_call *call, struct pri_sr *req, int activate);
 

Modified: team/group/ccss/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_internal.h?view=diff&rev=1344&r1=1343&r2=1344
==============================================================================
--- team/group/ccss/pri_internal.h (original)
+++ team/group/ccss/pri_internal.h Fri Nov 20 11:28:16 2009
@@ -583,6 +583,10 @@
 	CC_EVENT_CCBS_REQUEST,
 	/*! Requesting CCNR activation. */
 	CC_EVENT_CCNR_REQUEST,
+	/*! Requesting CCBS activation accepted. */
+	CC_EVENT_CCBS_REQUEST_ACCEPT,
+	/*! Requesting CCNR activation accepted. */
+	CC_EVENT_CCNR_REQUEST_ACCEPT,
 	/*! CC party B is available. */
 	CC_EVENT_REMOTE_USER_FREE,
 	/*! CC poll/prompt for party A status. */
@@ -632,7 +636,17 @@
 	struct q931_party_address party_b;
 /* BUGBUG need to record BC, HLC, and LLC from initial SETUP */
 
-	/*! TRUE if the remote party is party B. */
+	/*! Pending response information. */
+	struct {
+		/*! Send response on this signaling link. */
+		struct q931_call *signaling;
+		/*! Invoke operation code */
+		int invoke_operation;
+		/*! Invoke id to use in the pending response. */
+		short invoke_id;
+	} response;
+
+	/*! TRUE if the remote party is party B. (We are a monitor./We are the originator.) */
 	unsigned char party_b_is_remote;
 	/*! TRUE if party_a_busy status is valid. (PTMP) */
 	unsigned char party_a_status_valid;
@@ -727,6 +741,10 @@
 
 int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number);
 
+struct pri_cc_record *pri_cc_find_by_reference(struct pri *ctrl, unsigned reference_id);
+struct pri_cc_record *pri_cc_find_by_linkage(struct pri *ctrl, unsigned linkage_id);
+struct pri_cc_record *pri_cc_find_by_addressing(struct pri *ctrl, const struct q931_party_address *party_a, const struct q931_party_address *party_b);
+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);
 int pri_cc_event_down(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event);
@@ -785,4 +803,10 @@
 	return (call->cr == Q931_DUMMY_CALL_REFERENCE) ? 1 : 0;
 }
 
+static inline short get_invokeid(struct pri *ctrl)
+{
+	ctrl = PRI_MASTER(ctrl);
+	return ++ctrl->last_invoke;
+}
+
 #endif

Modified: team/group/ccss/q931.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/q931.c?view=diff&rev=1344&r1=1343&r2=1344
==============================================================================
--- team/group/ccss/q931.c (original)
+++ team/group/ccss/q931.c Fri Nov 20 11:28:16 2009
@@ -30,10 +30,7 @@
 #include "compat.h"
 #include "libpri.h"
 #include "pri_internal.h"
-#include "pri_q921.h"
-#include "pri_q931.h"
 #include "pri_facility.h"
-#include "rose.h"
 
 #include <unistd.h>
 #include <stdlib.h>
@@ -306,16 +303,18 @@
 	case Q931_HOLD_STATE_RETRIEVE_REQ:
 	case Q931_HOLD_STATE_RETRIEVE_IND:
 		held_call = 1 << 18;
-
-		/* So a -1 does not wipe out the held_call flag. */
+		break;
+	default:
+		held_call = 0;
+		break;
+	}
+	if (held_call || call->cis_call) {
+		/* So a -1 does not wipe out the held_call or cis_call flags. */
 		channelno = call->channelno & 0xFF;
 		ds1no = call->ds1no & 0xFF;
-		break;
-	default:
-		held_call = 0;
+	} else {
 		channelno = call->channelno;
 		ds1no = call->ds1no;
-		break;
 	}
 	return channelno | (ds1no << 8) | (call->ds1explicit << 16) | (call->cis_call << 17)
 		| held_call;
@@ -6088,7 +6087,6 @@
 
 		if (allow_posthandle) {
 			res = post_handle_q931_message(ctrl, mh, c, missingmand);
-
 			if (res == Q931_RES_HAVEEVENT && !allow_event) {
 				res = 0;
 			}
@@ -6564,7 +6562,11 @@
 	ctrl->ev.facility.subcmds = &ctrl->subcmds;
 	ctrl->ev.facility.channel = q931_encode_channel(call);
 	ctrl->ev.facility.cref = call->cr;
-	ctrl->ev.facility.call = call->master_call;
+	if (q931_is_dummy_call(call)) {
+		ctrl->ev.facility.call = NULL;
+	} else {
+		ctrl->ev.facility.call = call->master_call;
+	}
 	ctrl->ev.facility.subcall = call;
 
 	/* Need to do this for backward compatibility with struct pri_event_facname */




More information about the libpri-commits mailing list