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

SVN commits to the libpri project libpri-commits at lists.digium.com
Thu Nov 12 10:50:58 CST 2009


Author: rmudgett
Date: Thu Nov 12 10:50:54 2009
New Revision: 1302

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

*  Added call completion configuration options to the public API.
*  Added responding to cc-available messages from ETSI PTP and PTMP.
*  Added initial outline for call completion state machine.

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_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=1302&r1=1301&r2=1302
==============================================================================
--- team/group/ccss/libpri.h (original)
+++ team/group/ccss/libpri.h Thu Nov 12 10:50:54 2009
@@ -554,8 +554,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_REQ		15	/*!< CC deactivation request */
-#define PRI_SUBCMD_CC_DEACTIVATE_RSP		16	/*!< CC deactivation request response */
+#define PRI_SUBCMD_CC_DEACTIVATE_RSP		15	/*!< CC deactivation request response */
 
 struct pri_subcmd_status_request {
 	/*!
@@ -624,6 +623,10 @@
 	 * \note Use pri_facility_error2str() to convert the error_code.
 	 */
 	int error_code;
+	/*!
+	 * \brief TRUE if negotiated to retain CC service if B busy again.
+	 */
+	int retain_service;
 };
 
 struct pri_subcmd_cc_status {
@@ -727,7 +730,6 @@
 		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_id cc_deactivate_req;
 		struct pri_subcmd_cc_deactivate_rsp cc_deactivate_rsp;
 
 /* BUGBUG eliminate these struct members. */
@@ -1497,7 +1499,58 @@
 int pri_status_req(struct pri *ctrl, int request_id, const struct pri_sr *req);
 void pri_status_req_rsp(struct pri *ctrl, int invoke_id, int status);
 
-/* Call-completion function prototypes */
+/*!
+ * \brief Set the call completion feature enable flag.
+ *
+ * \param ctrl D channel controller.
+ * \param enable TRUE to enable call completion feature.
+ *
+ * \return Nothing
+ */
+void pri_cc_enable(struct pri *ctrl, int enable);
+
+/*!
+ * \brief Set the PTMP NT call completion recall mode.
+ *
+ * \param ctrl D channel controller.
+ * \param mode globalRecall(0), specificRecall(1)
+ *
+ * \return Nothing
+ */
+void pri_cc_recall_mode(struct pri *ctrl, int mode);
+
+/*!
+ * \brief Set the call completion service retention mode if party B is busy again.
+ *
+ * \param ctrl D channel controller.
+ * \param retain_service TRUE if can retain cc service if party B is unavailable again.
+ *
+ * \return Nothing
+ */
+void pri_cc_retain_service(struct pri *ctrl, int retain_service);
+
+/*!
+ * \brief Set the Q.SIG call completion signaling link retention mode.
+ * (Requestor/Initiator/Originator/Party-A)
+ *
+ * \param ctrl D channel controller.
+ * \param signaling_retention release(0), retain(1), do-not-care(2).
+ *
+ * \return Nothing
+ */
+void pri_cc_retain_signaling_req(struct pri *ctrl, int signaling_retention);
+
+/*!
+ * \brief Set the Q.SIG call completion signaling link retention mode.
+ * (Responder/Answerer/Party-B)
+ *
+ * \param ctrl D channel controller.
+ * \param signaling_retention release(0), retain(1).
+ *
+ * \return Nothing
+ */
+void pri_cc_retain_signaling_rsp(struct pri *ctrl, int signaling_retention);
+
 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);

Modified: team/group/ccss/pri.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri.c?view=diff&rev=1302&r1=1301&r2=1302
==============================================================================
--- team/group/ccss/pri.c (original)
+++ team/group/ccss/pri.c Thu Nov 12 10:50:54 2009
@@ -107,6 +107,9 @@
 	{ "CCBS-T2",        PRI_TIMER_QSIG_CCBS_T2,     PRI_BIT(PRI_SWITCH_QSIG) },
 	{ "CCNR-T2",        PRI_TIMER_QSIG_CCNR_T2,     PRI_BIT(PRI_SWITCH_QSIG) },
 	{ "CC-T3",          PRI_TIMER_QSIG_CC_T3,       PRI_BIT(PRI_SWITCH_QSIG) },
+#if defined(QSIG_PATH_RESERVATION_SUPPORT)
+	{ "CC-T4",          PRI_TIMER_QSIG_CC_T4,       PRI_BIT(PRI_SWITCH_QSIG) },
+#endif	/* defined(QSIG_PATH_RESERVATION_SUPPORT) */
 /* *INDENT-ON* */
 };
 
@@ -199,6 +202,9 @@
 	ctrl->timers[PRI_TIMER_QSIG_CCBS_T2] = 60 * 60 * 1000;/* CCBS supervision timeout. */
 	ctrl->timers[PRI_TIMER_QSIG_CCNR_T2] = 195 * 60 * 1000;/* CCNR supervision timeout. */
 	ctrl->timers[PRI_TIMER_QSIG_CC_T3] = 30 * 1000;/* Max time to wait for user A to respond to user B availability. */
+#if defined(QSIG_PATH_RESERVATION_SUPPORT)
+	ctrl->timers[PRI_TIMER_QSIG_CC_T4] = 40 * 1000;/* Path reservation supervision timeout. */
+#endif	/* defined(QSIG_PATH_RESERVATION_SUPPORT) */
 
 	/* Set any switch specific override default values */
 	switch (switchtype) {
@@ -1696,3 +1702,43 @@
 {
 	call->ccoperation = cc_operation;
 }
+
+void pri_cc_enable(struct pri *ctrl, int enable)
+{
+	ctrl = PRI_MASTER(ctrl);
+	if (ctrl) {
+		ctrl->cc_support = enable ? 1 : 0;
+	}
+}
+
+void pri_cc_recall_mode(struct pri *ctrl, int mode)
+{
+	ctrl = PRI_MASTER(ctrl);
+	if (ctrl) {
+		ctrl->cc.option.recall_mode = mode ? 1 : 0;
+	}
+}
+
+void pri_cc_retain_service(struct pri *ctrl, int retain_service)
+{
+	ctrl = PRI_MASTER(ctrl);
+	if (ctrl) {
+		ctrl->cc.option.retain_service = retain_service ? 1 : 0;
+	}
+}
+
+void pri_cc_retain_signaling_req(struct pri *ctrl, int signaling_retention)
+{
+	ctrl = PRI_MASTER(ctrl);
+	if (ctrl && 0 <= signaling_retention && signaling_retention < 3) {
+		ctrl->cc.option.signaling_retention_req = signaling_retention;
+	}
+}
+
+void pri_cc_retain_signaling_rsp(struct pri *ctrl, int signaling_retention)
+{
+	ctrl = PRI_MASTER(ctrl);
+	if (ctrl) {
+		ctrl->cc.option.signaling_retention_rsp = signaling_retention ? 1 : 0;
+	}
+}

Modified: team/group/ccss/pri_cc.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_cc.c?view=diff&rev=1302&r1=1301&r2=1302
==============================================================================
--- team/group/ccss/pri_cc.c (original)
+++ team/group/ccss/pri_cc.c Thu Nov 12 10:50:54 2009
@@ -58,6 +58,7 @@
 {
 	struct pri_cc_record *cc_record;
 
+	ctrl = PRI_MASTER(ctrl);
 	for (cc_record = ctrl->cc.pool; cc_record; cc_record = cc_record->next) {
 		if (cc_record->ccbs_reference_id == reference_id) {
 			/* Found the record */
@@ -83,6 +84,7 @@
 {
 	struct pri_cc_record *cc_record;
 
+	ctrl = PRI_MASTER(ctrl);
 	for (cc_record = ctrl->cc.pool; cc_record; cc_record = cc_record->next) {
 		if (cc_record->call_linkage_id == linkage_id) {
 			/* Found the record */
@@ -107,6 +109,7 @@
 {
 	struct pri_cc_record *cc_record;
 
+	ctrl = PRI_MASTER(ctrl);
 	for (cc_record = ctrl->cc.pool; cc_record; cc_record = cc_record->next) {
 		if (cc_record->record_id == cc_id) {
 			/* Found the record */
@@ -133,6 +136,7 @@
 {
 	struct pri_cc_record *cc_record;
 
+	ctrl = PRI_MASTER(ctrl);
 	for (cc_record = ctrl->cc.pool; cc_record; cc_record = cc_record->next) {
 		if (!q931_cmp_party_id_to_address(&cc_record->party_a, party_a)
 			&& !q931_party_address_cmp(&cc_record->party_b, party_b)) {
@@ -162,6 +166,7 @@
 	long reference_id;
 	long first_id;
 
+	ctrl = PRI_MASTER(ctrl);
 	ctrl->cc.last_reference_id = (ctrl->cc.last_reference_id + 1) & 0x7F;
 	reference_id = ctrl->cc.last_reference_id;
 	first_id = reference_id;
@@ -194,6 +199,7 @@
 	long linkage_id;
 	long first_id;
 
+	ctrl = PRI_MASTER(ctrl);
 	ctrl->cc.last_linkage_id = (ctrl->cc.last_linkage_id + 1) & 0x7F;
 	linkage_id = ctrl->cc.last_linkage_id;
 	first_id = linkage_id;
@@ -225,6 +231,7 @@
 	long record_id;
 	long first_id;
 
+	ctrl = PRI_MASTER(ctrl);
 	record_id = ++ctrl->cc.last_record_id;
 	first_id = record_id;
 	while (pri_cc_find_by_id(ctrl, record_id)) {
@@ -243,9 +250,7 @@
 	return record_id;
 }
 
-#if defined(BUGBUG_NOT_USED_YET)
-/*!
- * \internal
+/*!
  * \brief Delete the given call completion record
  *
  * \param ctrl D channel controller.
@@ -253,11 +258,12 @@
  *
  * \return Nothing
  */
-static void pri_cc_delete_record(struct pri *ctrl, struct pri_cc_record *doomed)
+void pri_cc_delete_record(struct pri *ctrl, struct pri_cc_record *doomed)
 {
 	struct pri_cc_record **prev;
 	struct pri_cc_record *current;
 
+	ctrl = PRI_MASTER(ctrl);
 	for (prev = &ctrl->cc.pool, current = ctrl->cc.pool; current;
 		prev = &current->next, current = current->next) {
 		if (current == doomed) {
@@ -269,10 +275,8 @@
 
 	/* The doomed node is not in the call completion database */
 }
-#endif
-
-/*!
- * \internal
+
+/*!
  * \brief Allocate a new cc_record.
  *
  * \param ctrl D channel controller.
@@ -281,11 +285,12 @@
  * \retval pointer to new call completion record
  * \retval NULL if failed
  */
-static struct pri_cc_record *pri_cc_new_record(struct pri *ctrl, q931_call *call)
+struct pri_cc_record *pri_cc_new_record(struct pri *ctrl, q931_call *call)
 {
 	struct pri_cc_record *cc_record;
 	long record_id;
 
+	ctrl = PRI_MASTER(ctrl);
 	record_id = pri_cc_new_id(ctrl);
 	if (record_id < 0) {
 		return NULL;
@@ -300,7 +305,7 @@
 	cc_record->call_linkage_id = CC_PTMP_INVALID_ID;/* So it will never be found this way */
 	cc_record->ccbs_reference_id = CC_PTMP_INVALID_ID;/* So it will never be found this way */
 	cc_record->party_a = call->cc.party_a;
-	cc_record->party_b = call->cc.party_b;
+	cc_record->party_b = call->called;
 	cc_record->party_b_is_remote = call->cc.party_b_is_remote;
 /* BUGBUG need to record BC, HLC, and LLC from initial SETUP */
 /*! \todo BUGBUG need more initialization?? */
@@ -310,6 +315,72 @@
 	ctrl->cc.pool = cc_record;
 
 	return cc_record;
+}
+
+/*!
+ * \brief Send an event from the upper layer to the cc state machine.
+ *
+ * \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.
+ *
+ * \retval 0 if no error or event.
+ * \retval Q931_RES_HAVEEVENT if have an event.
+ * \retval -1 on error.
+ */
+int pri_cc_event_down(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
+{
+	int res;
+
+	switch (ctrl->switchtype) {
+	case PRI_SWITCH_QSIG:
+		res = 0;
+		break;
+	case PRI_SWITCH_EUROISDN_E1:
+	case PRI_SWITCH_EUROISDN_T1:
+		res = 0;
+		break;
+	default:
+		res = 0;
+		break;
+	}
+
+	return res;
+	/*! \todo BUGBUG pri_cc_event_down() not written */
+}
+
+/*!
+ * \brief Send an event from the link to the cc state machine.
+ *
+ * \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.
+ *
+ * \retval 0 if no error or event.
+ * \retval Q931_RES_HAVEEVENT if have an event.
+ * \retval -1 on error.
+ */
+int pri_cc_event_up(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event)
+{
+	int res;
+
+	switch (ctrl->switchtype) {
+	case PRI_SWITCH_QSIG:
+		res = 0;
+		break;
+	case PRI_SWITCH_EUROISDN_E1:
+	case PRI_SWITCH_EUROISDN_T1:
+		res = 0;
+		break;
+	default:
+		res = 0;
+		break;
+	}
+
+	return res;
+	/*! \todo BUGBUG pri_cc_event_up() not written */
 }
 
 /*!
@@ -364,6 +435,7 @@
 			if (!cc_record) {
 				break;
 			}
+			cc_record->signaling = PRI_MASTER(ctrl)->dummy_call;
 			cc_record->call_linkage_id = linkage_id;
 		} else {
 			cc_record = pri_cc_new_record(ctrl, call);

Modified: team/group/ccss/pri_facility.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_facility.c?view=diff&rev=1302&r1=1301&r2=1302
==============================================================================
--- team/group/ccss/pri_facility.c (original)
+++ team/group/ccss/pri_facility.c Thu Nov 12 10:50:54 2009
@@ -3723,6 +3723,7 @@
 void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie,
 	const struct fac_extension_header *header, const struct rose_msg_invoke *invoke)
 {
+	struct pri_cc_record *cc_record;
 	struct pri_subcommand *subcmd;
 	struct q931_party_id party_id;
 	struct q931_party_redirecting deflection;
@@ -4061,8 +4062,41 @@
 	case ROSE_ETSI_StatusRequest:
 		break;
 #endif	/* Not handled yet */
-#if 0	/* Not handled yet */
 	case ROSE_ETSI_CallInfoRetain:
+		if (!PRI_MASTER(ctrl)->cc_support) {
+			/*
+			 * Blocking the cc-available event effectively
+			 * disables call completion for outgoing calls.
+			 */
+			break;
+		}
+		/*
+		 * Since we received this facility, we will not be allocating any
+		 * reference and linkage id's.
+		 */
+		if (call->cc.record) {
+			/* Duplicate message!  Should not happen. */
+			break;
+		}
+		cc_record = pri_cc_new_record(ctrl, call);
+		if (!cc_record) {
+			break;
+		}
+		cc_record->signaling = PRI_MASTER(ctrl)->dummy_call;
+		cc_record->call_linkage_id =
+			invoke->args.etsi.CallInfoRetain.call_linkage_id & 0x7F;
+		cc_record->state = CC_STATE_AVAILABLE;
+
+		subcmd = q931_alloc_subcommand(ctrl);
+		if (!subcmd) {
+			pri_cc_delete_record(ctrl, cc_record);
+			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_CCBSRequest:
 		break;
@@ -4095,16 +4129,40 @@
 	case ROSE_ETSI_CCBS_T_RemoteUserFree:
 		break;
 	case ROSE_ETSI_CCBS_T_Available:
-		break;
-#endif	/* Not handled yet */
-#if 0	/* Not handled yet */
+		if (!PRI_MASTER(ctrl)->cc_support) {
+			/*
+			 * Blocking the cc-available event effectively
+			 * disables call completion for outgoing calls.
+			 */
+			break;
+		}
+		if (call->cc.record) {
+			/* Duplicate message!  Should not happen. */
+			break;
+		}
+		cc_record = pri_cc_new_record(ctrl, call);
+		if (!cc_record) {
+			break;
+		}
+		cc_record->state = CC_STATE_AVAILABLE;
+
+		subcmd = q931_alloc_subcommand(ctrl);
+		if (!subcmd) {
+			pri_cc_delete_record(ctrl, cc_record);
+			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:
 		break;
 	case ROSE_ETSI_CCNRInterrogate:
 		break;
 	case ROSE_ETSI_CCNR_T_Request:
 		break;
-#endif	/* Not handled yet */
 	case ROSE_QSIG_CallingName:
 		/* CallingName is put in remote_id.name */
 		rose_copy_name_to_q931(ctrl, &call->remote_id.name,

Modified: team/group/ccss/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_internal.h?view=diff&rev=1302&r1=1301&r2=1302
==============================================================================
--- team/group/ccss/pri_internal.h (original)
+++ team/group/ccss/pri_internal.h Thu Nov 12 10:50:54 2009
@@ -48,6 +48,13 @@
 
 struct pri_cc_record;
 
+/*
+ * libpri needs to be able to allocate B channels to support Q.SIG path reservation.
+ * Until that happens, path reservation is not possible.  Fortunately,
+ * path reservation is optional with a fallback to what we can implement.
+ */
+//#define QSIG_PATH_RESERVATION_SUPPORT	1
+
 /*! Maximum number of scheduled events active at the same time. */
 #define MAX_SCHED	(128 + 256) /* 256 CC supervision timer events */
 
@@ -74,6 +81,7 @@
 	unsigned int acceptinbanddisconnect:1;	/* Should we allow inband progress after DISCONNECT? */
 	unsigned int hold_support:1;/* TRUE if upper layer supports call hold. */
 	unsigned int deflection_support:1;/* TRUE if upper layer supports call deflection/rerouting. */
+	unsigned int cc_support:1;/* TRUE if upper layer supports call completion. */
 
 	/* Q.921 State */
 	int q921_state;	
@@ -143,7 +151,7 @@
 	short last_invoke;	/* Last ROSE invoke ID */
 	unsigned char sendfacility;
 
-	/*! Call completion */
+	/*! Call completion (Valid in master record only) */
 	struct {
 		/*! Active CC records */
 		struct pri_cc_record *pool;
@@ -153,6 +161,21 @@
 		unsigned char last_reference_id;
 		/*! Last CC PTMP linkage id allocated. (0-127) */
 		unsigned char last_linkage_id;
+		/*! Configured CC options. */
+		struct {
+			/*! PTMP recall mode: globalRecall(0), specificRecall(1) */
+			unsigned char recall_mode;
+			/*! TRUE if can retain cc service if party B is unavailable again. */
+			unsigned char retain_service;
+			/*! Q.SIG Request signaling link retention: release(0), retain(1), do-not-care(2) */
+			unsigned char signaling_retention_req;
+			/*! Q.SIG Response request signaling link retention: release(0), retain(1) */
+			unsigned char signaling_retention_rsp;
+#if defined(QSIG_PATH_RESERVATION_SUPPORT)
+			/*! Q.SIG TRUE if response request can support path reservation. */
+			unsigned char allow_path_reservation;
+#endif	/* defined(QSIG_PATH_RESERVATION_SUPPORT) */
+		} option;
 	} cc;
 };
 
@@ -313,6 +336,8 @@
 	const char *keypad_digits;
 	int transferable;
 	int reversecharge;
+
+/* BUGBUG these CC elements will not be retained. */
 	int ccbsnr;
 	int ccringout;
 };
@@ -536,8 +561,6 @@
 		struct pri_cc_record *record;
 		/*! Original calling party. */
 		struct q931_party_id party_a;
-		/*! Original called party. */
-		struct q931_party_address party_b;
 		/*! TRUE if the remote party is party B. */
 		unsigned char party_b_is_remote;
 /* BUGBUG need to record BC, HLC, and LLC from initial SETUP */
@@ -547,8 +570,8 @@
 enum CC_STATES {
 	/*! CC is not active. */
 	CC_STATE_IDLE,
-	/*! CC has recorded call information in anticipation of CC availability. */
-	CC_STATE_RECORD_RETENTION,
+	// /*! CC has recorded call information in anticipation of CC availability. */
+	// CC_STATE_RECORD_RETENTION,
 	/*! CC is available and waiting on ALERTING or DISCONNECT to go out. */
 	CC_STATE_PENDING_AVAILABLE,
 	/*! CC is available and waiting on possible CC request. */
@@ -559,10 +582,39 @@
 	CC_STATE_ACTIVATED,
 	/*! CC party B is available and waiting for status of party A. */
 	CC_STATE_B_AVAILABLE,
-	/*! CC is suspended because party A is not available. */
+	/*! CC is suspended because party A is not available. (Monitor party A.) */
 	CC_STATE_SUSPENDED,
 	/*! CC is waiting for party A to initiate CC callback. */
 	CC_STATE_WAIT_CALLBACK,
+	/*! CC is waiting for signaling link to be cleared before destruction. */
+	CC_STATE_WAIT_DESTRUCTION,
+};
+
+enum CC_EVENTS {
+	/*! CC is available for the current call. */
+	CC_EVENT_AVAILABLE,
+	/*! Requesting CCBS activation. */
+	CC_EVENT_CCBS_REQUEST,
+	/*! Requesting CCNR activation. */
+	CC_EVENT_CCNR_REQUEST,
+	/*! CC party B is available. */
+	CC_EVENT_REMOTE_USER_FREE,
+	/*! CC poll/prompt for party A status. */
+	CC_EVENT_A_STATUS,
+	/*! CC party A is free/available for recall. */
+	CC_EVENT_A_FREE,
+	/*! CC party A is busy/not-available for recall. */
+	CC_EVENT_A_BUSY,
+	/*! Suspend monitoring party B because party A is busy. */
+	CC_EVENT_SUSPEND,
+	/*! Resume monitoring party B because party A is now available. */
+	CC_EVENT_RESUME,
+	/*! This is the call completion recall call attempt. */
+	CC_EVENT_RECALL,
+	/*! Tear down call completion request. */
+	CC_EVENT_CANCEL,
+	/*! Tear down of call completion completed. */
+	CC_EVENT_CANCEL_COMPLETE,
 };
 
 /* Invalid PTMP call completion reference and linkage id value. */
@@ -572,6 +624,18 @@
 struct pri_cc_record {
 	/*! Next call-completion record in the list */
 	struct pri_cc_record *next;
+	/*!
+	 * \brief Associated signaling link. (NULL if not established.)
+	 * \note
+	 * PTMP - Broadcast dummy call reference call.
+	 * (If needed, the TE side could use this pointer to locate its specific
+	 * dummy call reference call.)
+	 * \note
+	 * PTP - REGISTER signaling link.
+	 * \note
+	 * Q.SIG - SETUP signaling link.
+	 */
+	struct q931_call *signaling;
 	/*! Call-completion record id (0 - 65535) */
 	long record_id;
 	/*! Call-completion state */
@@ -584,10 +648,27 @@
 
 	/*! TRUE if the remote party is party B. */
 	unsigned char party_b_is_remote;
+	/*! TRUE if party_a_busy status is valid. (PTMP) */
+	unsigned char party_a_status_valid;
+	/*! TRUE if the status of party A is busy. (PTMP) */
+	unsigned char party_a_busy;
 	/*! PTMP pre-activation reference id. (0-127) */
 	unsigned char call_linkage_id;
 	/*! PTMP active CCBS reference id. (0-127) */
 	unsigned char ccbs_reference_id;
+	/*! Negotiated options */
+	struct {
+		/*! PTMP recall mode: globalRecall(0), specificRecall(1) */
+		unsigned char recall_mode;
+		/*! TRUE if can retain cc service if party B is unavailable again. */
+		unsigned char retain_service;
+		/*! TRUE if Q.SIG signaling link is retained. */
+		unsigned char retain_signaling_link;
+#if defined(QSIG_PATH_RESERVATION_SUPPORT)
+		/*! Q.SIG TRUE if can do path reservation. */
+		unsigned char do_path_reservation;
+#endif	/* defined(QSIG_PATH_RESERVATION_SUPPORT) */
+	} option;
 };
 
 /*! D channel control structure with associated dummy call reference record. */
@@ -659,6 +740,11 @@
 struct pri_subcommand *q931_alloc_subcommand(struct pri *ctrl);
 
 int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number);
+
+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);
+int pri_cc_event_up(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event);
 
 static inline struct pri * PRI_MASTER(struct pri *mypri)
 {

Modified: team/group/ccss/q931.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/q931.c?view=diff&rev=1302&r1=1301&r2=1302
==============================================================================
--- team/group/ccss/q931.c (original)
+++ team/group/ccss/q931.c Thu Nov 12 10:50:54 2009
@@ -4835,7 +4835,6 @@
 
 	/* Save the initial cc-parties. */
 	c->cc.party_a = c->local_id;
-	c->cc.party_b = c->called;
 	c->cc.party_b_is_remote = 1;
 
 	if (ctrl->subchannel && !ctrl->bri)
@@ -6749,7 +6748,6 @@
 
 		/* Save the initial cc-parties. (Incoming SETUP can only be a master call.) */
 		c->cc.party_a = c->remote_id;
-		c->cc.party_b = c->called;
 		c->cc.party_b_is_remote = 0;
 
 		q931_fill_ring_event(ctrl, c);




More information about the libpri-commits mailing list