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

SVN commits to the libpri project libpri-commits at lists.digium.com
Mon Nov 9 16:37:46 CST 2009


Author: rmudgett
Date: Mon Nov  9 16:37:42 2009
New Revision: 1274

URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1274
Log:
Current call completion work in progress.

*  Preliminary support for sending cc-available messages.
*  Collected struct pri and struct q931_call cc elements into a substruct.

Modified:
    team/group/ccss/libpri.h
    team/group/ccss/pri_cc.c
    team/group/ccss/pri_facility.c
    team/group/ccss/pri_facility.h
    team/group/ccss/pri_internal.h
    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=1274&r1=1273&r2=1274
==============================================================================
--- team/group/ccss/libpri.h (original)
+++ team/group/ccss/libpri.h Mon Nov  9 16:37:42 2009
@@ -1490,7 +1490,7 @@
 void pri_status_req_rsp(struct pri *ctrl, int invoke_id, int status);
 
 /* Call-completion function prototypes */
-void pri_cc_available(struct pri *ctrl, q931_call *call);
+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);
 void pri_cc_remote_user_free(struct pri *ctrl, long cc_id);

Modified: team/group/ccss/pri_cc.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_cc.c?view=diff&rev=1274&r1=1273&r2=1274
==============================================================================
--- team/group/ccss/pri_cc.c (original)
+++ team/group/ccss/pri_cc.c Mon Nov  9 16:37:42 2009
@@ -58,7 +58,7 @@
 {
 	struct pri_cc_record *cc_record;
 
-	for (cc_record = ctrl->cc_pool; cc_record; cc_record = cc_record->next) {
+	for (cc_record = ctrl->cc.pool; cc_record; cc_record = cc_record->next) {
 		if (cc_record->ccbs_reference_id == reference_id) {
 			/* Found the record */
 			break;
@@ -69,7 +69,6 @@
 }
 #endif
 
-#if defined(BUGBUG_NOT_USED_YET)
 /*!
  * \internal
  * \brief Find a cc_record by the PTMP linkage_id.
@@ -84,7 +83,7 @@
 {
 	struct pri_cc_record *cc_record;
 
-	for (cc_record = ctrl->cc_pool; cc_record; cc_record = cc_record->next) {
+	for (cc_record = ctrl->cc.pool; cc_record; cc_record = cc_record->next) {
 		if (cc_record->call_linkage_id == linkage_id) {
 			/* Found the record */
 			break;
@@ -93,7 +92,6 @@
 
 	return cc_record;
 }
-#endif
 
 /*!
  * \internal
@@ -109,7 +107,7 @@
 {
 	struct pri_cc_record *cc_record;
 
-	for (cc_record = ctrl->cc_pool; cc_record; cc_record = cc_record->next) {
+	for (cc_record = ctrl->cc.pool; cc_record; cc_record = cc_record->next) {
 		if (cc_record->record_id == cc_id) {
 			/* Found the record */
 			break;
@@ -135,7 +133,7 @@
 {
 	struct pri_cc_record *cc_record;
 
-	for (cc_record = ctrl->cc_pool; cc_record; cc_record = cc_record->next) {
+	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)) {
 			/* Found the record */
@@ -152,6 +150,69 @@
 #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)
+{
+	long reference_id;
+	long first_id;
+
+	ctrl->cc.last_reference_id = (ctrl->cc.last_reference_id + 1) & 0x7F;
+	reference_id = ctrl->cc.last_reference_id;
+	first_id = reference_id;
+	while (pri_cc_find_by_reference(ctrl, reference_id)) {
+		ctrl->cc.last_reference_id = (ctrl->cc.last_reference_id + 1) & 0x7F;
+		reference_id = ctrl->cc.last_reference_id;
+		if (reference_id == first_id) {
+			/* We probably have a resource leak. */
+			pri_error(ctrl, "PTMP call completion reference id exhaustion!\n");
+			reference_id = -1;
+			break;
+		}
+	}
+
+	return reference_id;
+}
+#endif
+
+/*!
+ * \internal
+ * \brief Allocate a new cc_record linkage id.
+ *
+ * \param ctrl D channel controller.
+ *
+ * \retval linkage_id on success.
+ * \retval -1 on error.
+ */
+static int pri_cc_new_linkage_id(struct pri *ctrl)
+{
+	long linkage_id;
+	long first_id;
+
+	ctrl->cc.last_linkage_id = (ctrl->cc.last_linkage_id + 1) & 0x7F;
+	linkage_id = ctrl->cc.last_linkage_id;
+	first_id = linkage_id;
+	while (pri_cc_find_by_linkage(ctrl, linkage_id)) {
+		ctrl->cc.last_linkage_id = (ctrl->cc.last_linkage_id + 1) & 0x7F;
+		linkage_id = ctrl->cc.last_linkage_id;
+		if (linkage_id == first_id) {
+			/* We probably have a resource leak. */
+			pri_error(ctrl, "PTMP call completion linkage id exhaustion!\n");
+			linkage_id = -1;
+			break;
+		}
+	}
+
+	return linkage_id;
+}
+
+/*!
+ * \internal
  * \brief Allocate a new cc_record id.
  *
  * \param ctrl D channel controller.
@@ -164,16 +225,16 @@
 	long record_id;
 	long first_id;
 
-	record_id = ++ctrl->last_cc_id;
+	record_id = ++ctrl->cc.last_record_id;
 	first_id = record_id;
 	while (pri_cc_find_by_id(ctrl, record_id)) {
-		record_id = ++ctrl->last_cc_id;
+		record_id = ++ctrl->cc.last_record_id;
 		if (record_id == first_id) {
 			/*
 			 * We have a resource leak.
 			 * We should never need to allocate 64k records on a D channel.
 			 */
-			pri_error(ctrl, "ERROR Too many call completion records!\n");
+			pri_error(ctrl, "Too many call completion records!\n");
 			record_id = -1;
 			break;
 		}
@@ -181,7 +242,6 @@
 
 	return record_id;
 }
-#endif
 
 #if defined(BUGBUG_NOT_USED_YET)
 /*!
@@ -198,7 +258,7 @@
 	struct pri_cc_record **prev;
 	struct pri_cc_record *current;
 
-	for (prev = &ctrl->cc_pool, current = ctrl->cc_pool; current;
+	for (prev = &ctrl->cc.pool, current = ctrl->cc.pool; current;
 		prev = &current->next, current = current->next) {
 		if (current == doomed) {
 			*prev = current->next;
@@ -211,46 +271,46 @@
 }
 #endif
 
-#if defined(BUGBUG_NOT_USED_YET)
 /*!
  * \internal
  * \brief Allocate a new cc_record.
  *
  * \param ctrl D channel controller.
- *
- * \retval cc_id on success.
- * \retval -1 on error.
- */
-static long pri_cc_new_record(struct pri *ctrl)
+ * \param call Q.931 call leg.
+ *
+ * \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 *cc_record;
 	long record_id;
 
+	record_id = pri_cc_new_id(ctrl);
+	if (record_id < 0) {
+		return NULL;
+	}
 	cc_record = calloc(1, sizeof(*cc_record));
 	if (!cc_record) {
-		return -1;
-	}
-	record_id = pri_cc_new_id(ctrl);
-	if (record_id < 0) {
-		free(cc_record);
-		return -1;
+		return NULL;
 	}
 
 	/* Initialize the new record */
 	cc_record->record_id = record_id;
-	cc_record->call_linkage_id = 0xFF;/* Invalid so it will never be found this way */
-	cc_record->ccbs_reference_id = 0xFF;/* Invalid so it will never be found this way */
-	q931_party_id_init(&cc_record->party_a);
-	q931_party_address_init(&cc_record->party_b);
+	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_is_remote = call->cc.party_b_is_remote;
+/* BUGBUG need to record BC, HLC, and LLC from initial SETUP */
 /*! \todo BUGBUG need more initialization?? */
 
 	/* Insert the new record into the database */
-	cc_record->next = ctrl->cc_pool;
-	ctrl->cc_pool = cc_record;
-
-	return record_id;
-}
-#endif
+	cc_record->next = ctrl->cc.pool;
+	ctrl->cc.pool = cc_record;
+
+	return cc_record;
+}
 
 /*!
  * \brief Indicate to the far end that CCBS/CCNR is available.
@@ -262,28 +322,68 @@
  * The CC available indication will go out with the next
  * DISCONNECT(busy/congested)/ALERTING message.
  *
- * \return Nothing
- */
-void pri_cc_available(struct pri *ctrl, q931_call *call)
-{
-	switch (ctrl->switchtype) {
-	case PRI_SWITCH_QSIG:
+ * \retval cc_id on success for subsequent reference.
+ * \retval -1 on error.
+ */
+long pri_cc_available(struct pri *ctrl, q931_call *call)
+{
+	struct pri_cc_record *cc_record;
+	long cc_id;
+
+	if (call->cc.record) {
+		/* This call is already associated with call completion. */
+		return -1;
+	}
+
+	cc_record = NULL;
+
+	switch (ctrl->switchtype) {
+	case PRI_SWITCH_QSIG:
+		cc_record = pri_cc_new_record(ctrl, call);
+		if (!cc_record) {
+			break;
+		}
+
 		/*
 		 * Q.SIG has no message to send when CC is available.
 		 * Q.SIG assumes CC is always available and is denied when
 		 * requested if CC is not possible or allowed.
 		 */
-		break;
-	case PRI_SWITCH_EUROISDN_E1:
-	case PRI_SWITCH_EUROISDN_T1:
-		if (q931_is_ptmp(ctrl)) {
-		} else {
-		}
-		/*! \todo BUGBUG pri_cc_available() not written */
-		break;
-	default:
-		break;
-	}
+		cc_record->state = CC_STATE_AVAILABLE;
+		break;
+	case PRI_SWITCH_EUROISDN_E1:
+	case PRI_SWITCH_EUROISDN_T1:
+		if (q931_is_ptmp(ctrl)) {
+			int linkage_id;
+
+			linkage_id = pri_cc_new_linkage_id(ctrl);
+			if (linkage_id < 0) {
+				break;
+			}
+			cc_record = pri_cc_new_record(ctrl, call);
+			if (!cc_record) {
+				break;
+			}
+			cc_record->call_linkage_id = linkage_id;
+		} else {
+			cc_record = pri_cc_new_record(ctrl, call);
+			if (!cc_record) {
+				break;
+			}
+		}
+		cc_record->state = CC_STATE_PENDING_AVAILABLE;
+		break;
+	default:
+		break;
+	}
+
+	call->cc.record = cc_record;
+	if (cc_record) {
+		cc_id = cc_record->record_id;
+	} else {
+		cc_id = -1;
+	}
+	return cc_id;
 }
 
 /*!
@@ -309,10 +409,6 @@
 	cc_record = pri_cc_find_by_id(ctrl, cc_id);
 	if (!cc_record) {
 		return -1;
-	}
-
-	if (cc_record->state == CC_STATE_IDLE) {
-		cc_record->party_b_is_remote = 1;
 	}
 
 	switch (ctrl->switchtype) {

Modified: team/group/ccss/pri_facility.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_facility.c?view=diff&rev=1274&r1=1273&r2=1274
==============================================================================
--- team/group/ccss/pri_facility.c (original)
+++ team/group/ccss/pri_facility.c Mon Nov  9 16:37:42 2009
@@ -3336,6 +3336,111 @@
 		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, NULL);
 }
 
 /*!

Modified: team/group/ccss/pri_facility.h
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_facility.h?view=diff&rev=1274&r1=1273&r2=1274
==============================================================================
--- team/group/ccss/pri_facility.h (original)
+++ team/group/ccss/pri_facility.h Mon Nov  9 16:37:42 2009
@@ -87,6 +87,8 @@
 int rose_connected_name_encode(struct pri *pri, q931_call *call, int messagetype);
 int rose_called_name_encode(struct pri *pri, q931_call *call, int messagetype);
 
+int rose_cc_available_encode(struct pri *ctrl, q931_call *call, int msgtype);
+
 /* Use this function to queue a facility-IE born APDU onto a call
  * call is the call to use, messagetype is any one of the Q931 messages,
  * apdu is the apdu data, apdu_len is the length of the apdu data  */

Modified: team/group/ccss/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/pri_internal.h?view=diff&rev=1274&r1=1273&r2=1274
==============================================================================
--- team/group/ccss/pri_internal.h (original)
+++ team/group/ccss/pri_internal.h Mon Nov  9 16:37:42 2009
@@ -116,9 +116,6 @@
 	q931_call **callpool;
 	q931_call *localpool;
 
-	/*! Active call-completion records */
-	struct pri_cc_record *cc_pool;
-
 	/* do we do overlap dialing */
 	int overlapdial;
 
@@ -136,10 +133,20 @@
 	unsigned int q931_rxcount;
 #endif
 
-	/*! Last CC id allocated. */
-	unsigned short last_cc_id;
 	short last_invoke;	/* Last ROSE invoke ID */
 	unsigned char sendfacility;
+
+	/*! Call completion */
+	struct {
+		/*! Active CC records */
+		struct pri_cc_record *pool;
+		/*! Last CC record id allocated. */
+		unsigned short last_record_id;
+		/*! Last CC PTMP reference id allocated. (0-127) */
+		unsigned char last_reference_id;
+		/*! Last CC PTMP linkage id allocated. (0-127) */
+		unsigned char last_linkage_id;
+	} cc;
 };
 
 /*! \brief Maximum name length plus null terminator (From ECMA-164) */
@@ -413,11 +420,6 @@
 	enum Q931_CALL_STATE ourcallstate;	/* Our call state */
 	enum Q931_CALL_STATE sugcallstate;	/* Status call state */
 
-/* BUGBUG These CC elements may not be retained. */
-	int ccoperation;		/* QSIG_CCBSREQUEST/QSIG_CCNRREQUEST */
-	int ccrequestresult;
-	int cctimer2;			/* Timer for QSIG-timer2 */
-
 	int ani2;               /* ANI II */
 
 	/*! Buffer for digits that come in KEYPAD_FACILITY */
@@ -518,6 +520,24 @@
 	/* These valid in master call only */
 	struct q931_call *subcalls[Q931_MAX_TEI];
 	int pri_winner;
+
+/* BUGBUG These CC elements will not be retained. (At least in this form) */
+	int ccoperation;		/* QSIG_CCBSREQUEST/QSIG_CCNRREQUEST */
+	int ccrequestresult;
+	int cctimer2;			/* Timer for QSIG-timer2 */
+
+	/* Call completion */
+	struct {
+		/*! CC record associated with this call. */
+		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 */
+	} cc;
 };
 
 enum CC_STATES {
@@ -525,6 +545,8 @@
 	CC_STATE_IDLE,
 	/*! 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. */
 	CC_STATE_AVAILABLE,
 	/*! CC is requested to be activated and waiting on party B to acknowledge. */
@@ -539,6 +561,9 @@
 	CC_STATE_WAIT_CALLBACK,
 };
 
+/* Invalid PTMP call completion reference and linkage id value. */
+#define CC_PTMP_INVALID_ID  0xFF
+
 /*! \brief Call-completion record */
 struct pri_cc_record {
 	/*! Next call-completion record in the list */
@@ -551,6 +576,7 @@
 	struct q931_party_id party_a;
 	/*! Original called party. */
 	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. */
 	unsigned char party_b_is_remote;

Modified: team/group/ccss/q931.c
URL: http://svnview.digium.com/svn/libpri/team/group/ccss/q931.c?view=diff&rev=1274&r1=1273&r2=1274
==============================================================================
--- team/group/ccss/q931.c (original)
+++ team/group/ccss/q931.c Mon Nov  9 16:37:42 2009
@@ -4328,6 +4328,17 @@
 		break;
 	}
 
+	if (c->cc.record) {
+		switch (c->cc.record->state) {
+		case CC_STATE_PENDING_AVAILABLE:
+			c->cc.record->state = CC_STATE_AVAILABLE;
+			rose_cc_available_encode(ctrl, c, Q931_ALERTING);
+			break;
+		default:
+			break;
+		}
+	}
+
 	return send_message(ctrl, c, Q931_ALERTING, alerting_ies);
 }
 
@@ -4557,6 +4568,18 @@
 		c->causecode = CODE_CCITT;
 		c->causeloc = LOC_PRIV_NET_LOCAL_USER;
 		c->sendhangupack = 1;
+
+		if (c->cc.record) {
+			switch (c->cc.record->state) {
+			case CC_STATE_PENDING_AVAILABLE:
+				c->cc.record->state = CC_STATE_AVAILABLE;
+				rose_cc_available_encode(ctrl, c, Q931_DISCONNECT);
+				break;
+			default:
+				break;
+			}
+		}
+
 		pri_schedule_del(ctrl, c->retranstimer);
 		c->retranstimer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T305], pri_disconnect_timeout, c);
 		return send_message(ctrl, c, Q931_DISCONNECT, disconnect_ies);
@@ -4734,6 +4757,11 @@
 		c->ccoperation = req->ccbsnr;
 
 	pri_call_add_standard_apdus(ctrl, c);
+
+	/* 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)
 		res = send_message(ctrl, c, Q931_SETUP, gr303_setup_ies);
@@ -6640,6 +6668,11 @@
 			q931_release_complete(ctrl, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL);
 			break;
 		}
+
+		/* 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);
 		return Q931_RES_HAVEEVENT;




More information about the libpri-commits mailing list