[svn-commits] rmudgett: branch 1.4 r2070 - /branches/1.4/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Oct 21 11:37:13 CDT 2010


Author: rmudgett
Date: Thu Oct 21 11:37:10 2010
New Revision: 2070

URL: http://svnview.digium.com/svn/libpri?view=rev&rev=2070
Log:
Restructure the Q.931 call record to layer 2 link association.

This is in anticipation of extracting a layer 2 link structure out of
struct pri.

Also completes fixing timer value access for the rest of libpri.  The
timer access must always be on the D channel control structure (Master).

May have fixed some events from timeouts not being passed to the upper
layer.  The timeout events must always be on the D channel control
structure (Master).

Modified:
    branches/1.4/pri.c
    branches/1.4/pri_facility.c
    branches/1.4/pri_internal.h
    branches/1.4/pri_q921.h
    branches/1.4/pri_q931.h
    branches/1.4/q921.c
    branches/1.4/q931.c

Modified: branches/1.4/pri.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri.c?view=diff&rev=2070&r1=2069&r2=2070
==============================================================================
--- branches/1.4/pri.c (original)
+++ branches/1.4/pri.c Thu Oct 21 11:37:10 2010
@@ -293,6 +293,7 @@
 		call = p->dummy_call;
 		if (call) {
 			pri_schedule_del(call->pri, call->retranstimer);
+			call->retranstimer = 0;
 			pri_call_apdu_queue_cleanup(call);
 		}
 		free(p->msg_line);
@@ -303,6 +304,7 @@
 
 struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri)
 {
+	int create_dummy_call;
 	struct d_ctrl_dummy *dummy_ctrl;
 	struct pri *p;
 
@@ -311,19 +313,32 @@
 	case PRI_SWITCH_GR303_TMC:
 	case PRI_SWITCH_GR303_TMC_SWITCHING:
 	case PRI_SWITCH_GR303_EOC_PATH:
+		create_dummy_call = 0;
+		break;
+	default:
+		if (bri && node == PRI_CPE && tei == Q921_TEI_GROUP) {
+			/*
+			 * BRI TE PTMP will not use its own group dummy call record.  It
+			 * will use the specific TEI dummy call instead.
+			 */
+			create_dummy_call = 0;
+		} else {
+			create_dummy_call = 1;
+		}
+		break;
+	}
+	if (create_dummy_call) {
+		dummy_ctrl = calloc(1, sizeof(*dummy_ctrl));
+		if (!dummy_ctrl) {
+			return NULL;
+		}
+		p = &dummy_ctrl->ctrl;
+	} else {
 		p = calloc(1, sizeof(*p));
 		if (!p) {
 			return NULL;
 		}
 		dummy_ctrl = NULL;
-		break;
-	default:
-		dummy_ctrl = calloc(1, sizeof(*dummy_ctrl));
-		if (!dummy_ctrl) {
-			return NULL;
-		}
-		p = &dummy_ctrl->ctrl;
-		break;
 	}
 	if (!master) {
 		/* This is the master record. */
@@ -402,12 +417,20 @@
 		break;
 	}
 
-	if (p->tei == Q921_TEI_GROUP && p->sapi == Q921_SAPI_LAYER2_MANAGEMENT && p->localtype == PRI_CPE) {
+	if (p->tei == Q921_TEI_GROUP && p->sapi == Q921_SAPI_LAYER2_MANAGEMENT
+		&& p->localtype == PRI_CPE) {
 		p->subchannel = __pri_new_tei(-1, p->localtype, p->switchtype, p, NULL, NULL, NULL, Q921_TEI_PRI, 1);
 		if (!p->subchannel) {
 			free(p);
 			return NULL;
 		}
+		/*
+		 * Make the group link use the just created specific TEI link
+		 * dummy call instead.  It makes no sense for TE PTMP interfaces
+		 * to broadcast messages on the dummy call or to broadcast any
+		 * messages for that matter.
+		 */
+		p->dummy_call = p->subchannel->dummy_call;
 	} else
 		q921_start(p);
 	

Modified: branches/1.4/pri_facility.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_facility.c?view=diff&rev=2070&r1=2069&r2=2070
==============================================================================
--- branches/1.4/pri_facility.c (original)
+++ branches/1.4/pri_facility.c Thu Oct 21 11:37:10 2010
@@ -2556,8 +2556,9 @@
 
 	switch (reason) {
 	case APDU_CALLBACK_REASON_MSG_RESULT:
-		call_2 = q931_find_call(ctrl, apdu->response.user.value);
-		if (!call_2) {
+		call_2 = apdu->response.user.ptr;
+		if (!q931_is_call_valid(ctrl, call_2)) {
+			/* Call is no longer present. */
 			break;
 		}
 
@@ -2636,7 +2637,7 @@
 	response.invoke_id = ctrl->last_invoke;
 	response.timeout_time = ctrl->timers[PRI_TIMER_T_RESPONSE];
 	response.callback = etsi_ect_link_id_rsp;
-	response.user.value = call_2->cr;
+	response.user.ptr = call_2;
 
 	/* Remember that if we queue a facility IE for a facility message we
 	 * have to explicitly send the facility message ourselves */

Modified: branches/1.4/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_internal.h?view=diff&rev=2070&r1=2069&r2=2070
==============================================================================
--- branches/1.4/pri_internal.h (original)
+++ branches/1.4/pri_internal.h Thu Oct 21 11:37:10 2010
@@ -448,9 +448,10 @@
 
 /* q931_call datastructure */
 struct q931_call {
-	struct pri *pri;	/* PRI */
+	struct pri *pri;	/* D channel controller (master) */
+	struct pri *link;	/* Q.921 link associated with this call. */
+	struct q931_call *next;
 	int cr;				/* Call Reference */
-	q931_call *next;
 	/* Slotmap specified (bitmap of channels 31/24-1) (Channel Identifier IE) (-1 means not specified) */
 	int slotmap;
 	/* An explicit channel (Channel Identifier IE) (-1 means not specified) */
@@ -914,7 +915,7 @@
 struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri);
 void __pri_free_tei(struct pri *p);
 
-void q931_init_call_record(struct pri *ctrl, struct q931_call *call, int cr);
+void q931_init_call_record(struct pri *link, struct q931_call *call, int cr);
 
 void pri_sr_init(struct pri_sr *req);
 

Modified: branches/1.4/pri_q921.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_q921.h?view=diff&rev=2070&r1=2069&r2=2070
==============================================================================
--- branches/1.4/pri_q921.h (original)
+++ branches/1.4/pri_q921.h Thu Oct 21 11:37:10 2010
@@ -195,7 +195,7 @@
 
 extern pri_event *q921_receive(struct pri *pri, q921_h *h, int len);
 
-extern int q921_transmit_iframe(struct pri *pri, int tei, void *buf, int len, int cr);
+int q921_transmit_iframe(struct pri *link, void *buf, int len, int cr);
 
 int q921_transmit_uiframe(struct pri *link, void *buf, int len);
 

Modified: branches/1.4/pri_q931.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_q931.h?view=diff&rev=2070&r1=2069&r2=2070
==============================================================================
--- branches/1.4/pri_q931.h (original)
+++ branches/1.4/pri_q931.h Thu Oct 21 11:37:10 2010
@@ -450,13 +450,11 @@
 
 extern int maintenance_service(struct pri *pri, int span, int channel, int changestatus);
 
-extern int maintenance_service_ack(struct pri *pri, q931_call *call);
-
 
 /* Q.SIG specific */
 #define QSIG_IE_TRANSIT_COUNT		0x31
 
-extern int q931_receive(struct pri *pri, int tei, q931_h *h, int len);
+int q931_receive(struct pri *link, q931_h *h, int len);
 
 extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
 
@@ -491,8 +489,7 @@
 
 extern int q931_call_setcrv(struct pri *pri, q931_call *call, int crv, int callmode);
 
-struct q931_call *q931_find_call(struct pri *ctrl, int cr);
-struct q931_call *q931_new_call(struct pri *pri);
+struct q931_call *q931_new_call(struct pri *ctrl);
 
 extern int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req);
 

Modified: branches/1.4/q921.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/q921.c?view=diff&rev=2070&r1=2069&r2=2070
==============================================================================
--- branches/1.4/q921.c (original)
+++ branches/1.4/q921.c Thu Oct 21 11:37:10 2010
@@ -798,41 +798,33 @@
 }
 
 /* This is the equivalent of a DL-DATA request, as well as the I-frame queued up outcome */
-int q921_transmit_iframe(struct pri *link, int tei, void *buf, int len, int cr)
+int q921_transmit_iframe(struct pri *link, void *buf, int len, int cr)
 {
 	q921_frame *f, *prev=NULL;
 	struct pri *ctrl;
 
 	ctrl = PRI_MASTER(link);
 
-	if (BRI_NT_PTMP(ctrl)) {
-		if (tei == Q921_TEI_GROUP) {
-			pri_error(ctrl, "Huh?! For NT-PTMP, we shouldn't be sending I-frames out the group TEI\n");
+	if (PTMP_MODE(ctrl)) {
+		if (link->tei == Q921_TEI_GROUP) {
+			pri_error(ctrl, "Huh?! For PTMP, we shouldn't be sending I-frames out the group TEI\n");
 			return 0;
 		}
-
-		link = pri_find_tei(ctrl, Q921_SAPI_CALL_CTRL, tei);
-		if (!link) {
-			pri_error(ctrl, "Huh?! Unable to locate PRI associated with TEI %d.  Did we have to ditch it due to error conditions?\n", tei);
-			return 0;
-		}
-	} else if (BRI_TE_PTMP(ctrl)) {
-		/* We don't care what the tei is, since we only support one sub and one TEI */
-		link = ctrl->subchannel;
-
-		switch (link->q921_state) {
-		case Q921_TEI_UNASSIGNED:
-			q921_setstate(link, Q921_ESTABLISH_AWAITING_TEI);
-			q921_tei_request(link);
-			break;
-		case Q921_ASSIGN_AWAITING_TEI:
-			q921_setstate(link, Q921_ESTABLISH_AWAITING_TEI);
-			break;
-		default:
-			break;
+		if (BRI_TE_PTMP(ctrl)) {
+			switch (link->q921_state) {
+			case Q921_TEI_UNASSIGNED:
+				q921_setstate(link, Q921_ESTABLISH_AWAITING_TEI);
+				q921_tei_request(link);
+				break;
+			case Q921_ASSIGN_AWAITING_TEI:
+				q921_setstate(link, Q921_ESTABLISH_AWAITING_TEI);
+				break;
+			default:
+				break;
+			}
 		}
 	} else {
-		/* Should just be PTP modes, which shouldn't have subs */
+		/* PTP modes, which shouldn't have subs */
 	}
 
 	/* Figure B.7/Q.921 Page 70 */
@@ -2269,9 +2261,9 @@
 		}
 		if (delay_q931_receive) {
 			/* Q.921 has finished processing the frame so we can give it to Q.931 now. */
-			res = q931_receive(link, link->tei, (q931_h *) h->i.data, len - 4);
+			res = q931_receive(link, (q931_h *) h->i.data, len - 4);
 			if (res != -1 && (res & Q931_RES_HAVEEVENT)) {
-				eres = &link->ev;
+				eres = &ctrl->ev;
 			}
 		}
 		break;
@@ -2519,9 +2511,9 @@
 			if (ctrl->debug & PRI_DEBUG_Q931_DUMP) {
 				q931_dump(ctrl, h->h.tei, (q931_h *) h->u.data, len - 3, 0);
 			}
-			res = q931_receive(link, link->tei, (q931_h *) h->u.data, len - 3);
+			res = q931_receive(link, (q931_h *) h->u.data, len - 3);
 			if (res != -1 && (res & Q931_RES_HAVEEVENT)) {
-				ev = &link->ev;
+				ev = &ctrl->ev;
 			}
 			break;
 		case 0x08:

Modified: branches/1.4/q931.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/q931.c?view=diff&rev=2070&r1=2069&r2=2070
==============================================================================
--- branches/1.4/q931.c (original)
+++ branches/1.4/q931.c Thu Oct 21 11:37:10 2010
@@ -3778,7 +3778,7 @@
 /*!
  * \brief Initialize the call record.
  *
- * \param ctrl D channel controller.
+ * \param link Q.921 link associated with the call.
  * \param call Q.931 call leg.
  * \param cr Call Reference identifier.
  *
@@ -3786,8 +3786,10 @@
  *
  * \return Nothing
  */
-void q931_init_call_record(struct pri *ctrl, struct q931_call *call, int cr)
-{
+void q931_init_call_record(struct pri *link, struct q931_call *call, int cr)
+{
+	struct pri *ctrl;
+
 	call->cr = cr;
 	call->slotmap = -1;
 	call->channelno = -1;
@@ -3822,15 +3824,17 @@
 	q931_party_number_init(&call->ani);
 	q931_party_redirecting_init(&call->redirecting);
 
-	/* PRI is set to whoever called us */
-	if (BRI_TE_PTMP(ctrl)) {
-		/*
-		 * Point to the master to avoid stale pointer problems if
-		 * the TEI is removed later.
-		 */
-		call->pri = PRI_MASTER(ctrl);
+	/* The call is now attached to whoever called us */
+	ctrl = PRI_MASTER(link);
+	call->pri = ctrl;
+	if (cr == Q931_DUMMY_CALL_REFERENCE) {
+		/* Dummy calls are always for the given link. */
+		call->link = link;
+	} else if (BRI_TE_PTMP(ctrl)) {
+		/* Always uses the specific TEI link. */
+		call->link = ctrl->subchannel;
 	} else {
-		call->pri = ctrl;
+		call->link = link;
 	}
 }
 
@@ -3838,17 +3842,20 @@
  * \internal
  * \brief Create a new call record.
  *
- * \param ctrl D channel controller.
+ * \param link Q.921 link associated with the call.
  * \param cr Call Reference identifier.
  *
  * \retval record on success.
  * \retval NULL on error.
  */
-static struct q931_call *q931_create_call_record(struct pri *ctrl, int cr)
+static struct q931_call *q931_create_call_record(struct pri *link, int cr)
 {
 	struct q931_call *call;
 	struct q931_call *prev;
-	struct pri *master;
+	struct pri *ctrl;
+
+	/* Find the master - He has the call pool */
+	ctrl = PRI_MASTER(link);
 
 	if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
 		pri_message(ctrl, "-- Making new call for cref %d\n", cr);
@@ -3860,62 +3867,60 @@
 	}
 
 	/* Initialize call structure. */
-	q931_init_call_record(ctrl, call, cr);
-
-	/* Find the master - He has the call pool */
-	master = PRI_MASTER(ctrl);
+	q931_init_call_record(link, call, cr);
 
 	/* Append to the list end */
-	if (*master->callpool) {
+	if (*ctrl->callpool) {
 		/* Find the list end. */
-		for (prev = *master->callpool; prev->next; prev = prev->next) {
+		for (prev = *ctrl->callpool; prev->next; prev = prev->next) {
 		}
 		prev->next = call;
 	} else {
 		/* List was empty. */
-		*master->callpool = call;
+		*ctrl->callpool = call;
 	}
 
 	return call;
 }
 
 /*!
+ * \internal
  * \brief Find a call in the active call pool.
  *
- * \param ctrl D channel controller.
+ * \param link Q.921 link associated with the call.
  * \param cr Call Reference identifier.
  *
  * \retval call if found.
  * \retval NULL if not found.
  */
-struct q931_call *q931_find_call(struct pri *ctrl, int cr)
+static struct q931_call *q931_find_call(struct pri *link, int cr)
 {
 	struct q931_call *cur;
-	struct pri *master;
+	struct pri *ctrl;
 
 	if (cr == Q931_DUMMY_CALL_REFERENCE) {
-		return ctrl->dummy_call;
+		return link->dummy_call;
 	}
 
 	/* Find the master - He has the call pool */
-	master = PRI_MASTER(ctrl);
+	ctrl = PRI_MASTER(link);
 
 	if (BRI_NT_PTMP(ctrl) && !(cr & Q931_CALL_REFERENCE_FLAG)) {
-		if (ctrl->tei == Q921_TEI_GROUP) {
-			/* Broadcast TEI.  This is bad.  We are using the wrong ctrl structure. */
+		if (link->tei == Q921_TEI_GROUP) {
+			/* Broadcast TEI.  This is bad.  We are using the wrong link structure. */
 			pri_error(ctrl, "Looking for cref %d when using broadcast TEI.\n", cr);
 			return NULL;
 		}
 
 		/* We are looking for a call reference value that the other side allocated. */
-		for (cur = *master->callpool; cur; cur = cur->next) {
-			if (cur->cr == cr && cur->pri == ctrl) {
-				/* Found existing call.  The call reference and TEI matched. */
+		for (cur = *ctrl->callpool; cur; cur = cur->next) {
+			if (cur->cr == cr && cur->link == link) {
+				/* Found existing call.  The call reference and link matched. */
 				break;
 			}
 		}
 	} else {
-		for (cur = *master->callpool; cur; cur = cur->next) {
+		for (cur = *ctrl->callpool; cur; cur = cur->next) {
 			if (cur->cr == cr) {
 				/* Found existing call. */
 				switch (ctrl->switchtype) {
@@ -3926,8 +3931,9 @@
 					break;
 				default:
 					if (!ctrl->bri) {
-						/* PRI is set to whoever called us */
+						/* The call is now attached to whoever called us */
 						cur->pri = ctrl;
+						cur->link = link;
 					}
 					break;
 				}
@@ -3938,51 +3944,72 @@
 	return cur;
 }
 
-static struct q931_call *q931_getcall(struct pri *ctrl, int cr)
+static struct q931_call *q931_getcall(struct pri *link, int cr)
 {
 	struct q931_call *cur;
-
-	cur = q931_find_call(ctrl, cr);
+	struct pri *ctrl;
+
+	cur = q931_find_call(link, cr);
 	if (cur) {
 		return cur;
 	}
+	if (cr == Q931_DUMMY_CALL_REFERENCE) {
+		/* Do not create new dummy call records. */
+		return NULL;
+	}
+	ctrl = PRI_MASTER(link);
+	if (link->tei == Q921_TEI_GROUP
+		&& BRI_NT_PTMP(ctrl)) {
+		/* Do not create NT PTMP broadcast call records here. */
+		pri_error(ctrl,
+			"NT PTMP cannot create call record for cref %d on the broadcast TEI.\n", cr);
+		return NULL;
+	}
 
 	/* No call record exists, make a new one */
-	return q931_create_call_record(ctrl, cr);
-}
-
+	return q931_create_call_record(link, cr);
+}
+
+/*!
+ * \brief Create a new call record for an outgoing call.
+ *
+ * \param ctrl D channel controller.
+ *
+ * \retval call on success.
+ * \retval NULL on error.
+ */
 struct q931_call *q931_new_call(struct pri *ctrl)
 {
 	struct q931_call *cur;
-	struct pri *master;
+	struct pri *link;
 	int first_cref;
 	int cref;
 
 	/* Find the master - He has the call pool */
-	master = PRI_MASTER(ctrl);
+	ctrl = PRI_MASTER(ctrl);
 
 	/* Find a new call reference value. */
-	first_cref = master->cref;
+	first_cref = ctrl->cref;
 	do {
-		cref = Q931_CALL_REFERENCE_FLAG | master->cref;
+		cref = Q931_CALL_REFERENCE_FLAG | ctrl->cref;
 
 		/* Next call reference. */
-		++master->cref;
-		if (!master->bri) {
-			if (master->cref > 32767) {
-				master->cref = 1;
+		++ctrl->cref;
+		if (!ctrl->bri) {
+			if (ctrl->cref > 32767) {
+				ctrl->cref = 1;
 			}
 		} else {
-			if (master->cref > 127) {
-				master->cref = 1;
+			if (ctrl->cref > 127) {
+				ctrl->cref = 1;
 			}
 		}
 
 		/* Is the call reference value in use? */
-		for (cur = *master->callpool; cur; cur = cur->next) {
+		for (cur = *ctrl->callpool; cur; cur = cur->next) {
 			if (cur->cr == cref) {
 				/* Yes it is in use. */
-				if (first_cref == master->cref) {
+				if (first_cref == ctrl->cref) {
 					/* All call reference values are in use! */
 					return NULL;
 				}
@@ -3991,7 +4018,8 @@
 		}
 	} while (cur);
 
-	return q931_create_call_record(ctrl, cref);
+	link = ctrl;
+	return q931_create_call_record(link, cref);
 }
 
 static void stop_t303(struct q931_call *call);
@@ -4475,20 +4503,27 @@
 	*mhb = mh;
 }
 
-static int q931_xmit(struct pri *ctrl, int tei, q931_h *h, int len, int cr, int uiframe)
-{
+static void q931_xmit(struct pri *link, q931_h *h, int len, int cr, int uiframe)
+{
+	struct pri *ctrl;
+
+	ctrl = PRI_MASTER(link);
 #ifdef LIBPRI_COUNTERS
 	ctrl->q931_txcount++;
 #endif
 	if (uiframe) {
-		q921_transmit_uiframe(ctrl, h, len);
+		if (link->tei != Q921_TEI_GROUP) {
+			pri_error(ctrl, "Huh?! Attempting to send UI-frame on TEI %d\n", link->tei);
+			return;
+		}
+		q921_transmit_uiframe(link, h, len);
 		if (ctrl->debug & PRI_DEBUG_Q931_DUMP) {
 			/*
 			 * The transmit operation might dump the Q.921 header, so logging
 			 * the Q.931 message body after the transmit puts the sections of
 			 * the message in the right order in the log,
 			 */
-			q931_dump(ctrl, tei, h, len, 1);
+			q931_dump(ctrl, link->tei, h, len, 1);
 		}
 	} else {
 		/*
@@ -4499,11 +4534,10 @@
 		 * Q.931 message as appropriate at that time.
 		 */
 		if (ctrl->debug & PRI_DEBUG_Q931_DUMP) {
-			q931_to_q921_passing_dump(ctrl, tei, h, len);
-		}
-		q921_transmit_iframe(ctrl, tei, h, len, cr);
-	}
-	return 0;
+			q931_to_q921_passing_dump(ctrl, link->tei, h, len);
+		}
+		q921_transmit_iframe(link, h, len, cr);
+	}
 }
 
 /*!
@@ -4532,12 +4566,18 @@
 	int x;
 	int codeset;
 	int uiframe;
-	int tei;
 
 	if (call->outboundbroadcast && call->master_call == call && msgtype != Q931_SETUP) {
 		pri_error(ctrl,
 			"Attempting to use master call record to send %s on BRI PTMP NT %p\n",
 			msg2str(msgtype), ctrl);
+		return -1;
+	}
+
+	if (!call->link) {
+		pri_error(ctrl,
+			"Call w/ cref:%d is not associated with a link.  TEI removed due to error conditions?\n",
+			call->cr);
 		return -1;
 	}
 
@@ -4561,7 +4601,6 @@
 	/* Invert the logic */
 	len = sizeof(buf) - len;
 
-	tei = call->pri->tei;
 	uiframe = 0;
 	if (BRI_NT_PTMP(ctrl)) {
 		/* NT PTMP is the only mode that can broadcast Q.931 messages. */
@@ -4578,7 +4617,7 @@
 			uiframe = 1;
 			break;
 		case Q931_FACILITY:
-			if (tei == Q921_TEI_GROUP) {
+			if (call->link->tei == Q921_TEI_GROUP) {
 				/* Broadcast TEI. */
 				if (q931_is_dummy_call(call)) {
 					/*
@@ -4600,24 +4639,18 @@
 		if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
 			/* This message is only interesting for NT PTMP mode. */
 			pri_message(ctrl,
-				"Sending message for call %p on call->pri: %p with TEI/SAPI %d/%d\n",
-				call, call->pri, call->pri->tei, call->pri->sapi);
-		}
-	} else if (call->pri->subchannel && BRI_TE_PTMP(ctrl)) {
-		/*
-		 * Get the best available TEI value for the debug dump display.
-		 * We may not actually have a TEI assigned at the moment.
-		 */
-		tei = call->pri->subchannel->tei;
-	}
-	q931_xmit(call->pri, tei, h, len, 1, uiframe);
+				"Sending message for call %p on call->link: %p with TEI/SAPI %d/%d\n",
+				call, call->link, call->link->tei, call->link->sapi);
+		}
+	}
+	q931_xmit(call->link, h, len, 1, uiframe);
 	call->acked = 1;
 	return 0;
 }
 
 static int maintenance_service_ies[] = { Q931_IE_CHANGE_STATUS, Q931_CHANNEL_IDENT, -1 };
 
-int maintenance_service_ack(struct pri *ctrl, q931_call *c)
+static int maintenance_service_ack(struct pri *ctrl, q931_call *c)
 {
 	int pd = MAINTENANCE_PROTOCOL_DISCRIMINATOR_1;
 	int mt = ATT_SERVICE_ACKNOWLEDGE;
@@ -4629,6 +4662,9 @@
 	return send_message(ctrl, c, (pd << 8) | mt, maintenance_service_ies);
 }
 
+/*!
+ * \note Maintenance service messages only supported in PRI mode.
+ */
 int maintenance_service(struct pri *ctrl, int span, int channel, int changestatus)
 {
 	struct q931_call *c;
@@ -5131,6 +5167,32 @@
 
 static int restart_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 };
 
+/*!
+ * \brief Send the RESTART message to the peer.
+ *
+ * \param ctrl D channel controller.
+ * \param channel Encoded channel id to use.
+ *
+ * \note
+ * Sending RESTART in NT PTMP mode is not supported at the
+ * present time.
+ *
+ * \note
+ * NT PTMP should broadcast the RESTART if there is a TEI
+ * allocated.  Otherwise it should immediately ACK the RESTART
+ * itself to avoid the T316 timeout delay (2 minutes) since
+ * there might not be anything connected.  The broadcast could
+ * be handled in a similar manner to the broadcast SETUP.
+ *
+ * \todo Need to implement T316 to protect against missing
+ * RESTART_ACKNOWLEDGE and STATUS messages.
+ *
+ * \todo NT PTMP mode should implement some protection from
+ * receiving a RESTART on channels in use by another TEI.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
 int q931_restart(struct pri *ctrl, int channel)
 {
 	struct q931_call *c;
@@ -5952,9 +6014,6 @@
 
 static void pri_create_fake_clearing(struct q931_call *c, struct pri *master)
 {
-	/* Point to the master so the timeout event can come out. */
-	c->pri = master;
-
 	pri_schedule_del(master, c->retranstimer);
 	c->retranstimer = pri_schedule_event(master, 0, pri_fake_clearing, c);
 }
@@ -6446,16 +6505,19 @@
 	}
 }
 
-static struct q931_call *q931_get_subcall(struct pri *ctrl, struct q931_call *master_call)
+static struct q931_call *q931_get_subcall(struct pri *link, struct q931_call *master_call)
 {
 	int i;
 	struct q931_call *cur;
+	struct pri *ctrl;
 	int firstfree = -1;
+
+	ctrl = PRI_MASTER(link);
 
 	/* First try to locate our subcall */
 	for (i = 0; i < ARRAY_LEN(master_call->subcalls); ++i) {
 		if (master_call->subcalls[i]) {
-			if (master_call->subcalls[i]->pri == ctrl) {
+			if (master_call->subcalls[i]->link == link) {
 				return master_call->subcalls[i];
 			}
 		} else if (firstfree == -1) {
@@ -6475,7 +6537,8 @@
 		return NULL;
 	}
 	*cur = *master_call;
-	cur->pri = ctrl;
+	//cur->pri = ctrl;/* We get this assignment for free. */
+	cur->link = link;
 	cur->next = NULL;
 	cur->apdus = NULL;
 	cur->bridged_call = NULL;
@@ -6495,16 +6558,17 @@
 
 	if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
 		pri_message(ctrl, "Adding subcall %p for TEI %d to call %p at position %d\n",
-			cur, ctrl->tei, master_call, firstfree);
+			cur, link->tei, master_call, firstfree);
 	}
 	/* Should only get here if the TEI is not found */
 	return cur;
 }
 
-int q931_receive(struct pri *ctrl, int tei, q931_h *h, int len)
+int q931_receive(struct pri *link, q931_h *h, int len)
 {
 	q931_mh *mh;
 	struct q931_call *c;
+	struct pri *ctrl;
 	q931_ie *ie;
 	unsigned int x;
 	int y;
@@ -6518,6 +6582,7 @@
 	int allow_event;
 	int allow_posthandle;
 
+	ctrl = PRI_MASTER(link);
 	memset(last_ie, 0, sizeof(last_ie));
 #ifdef LIBPRI_COUNTERS
 	ctrl->q931_rxcount++;
@@ -6537,7 +6602,7 @@
 			   KLUDGE this by changing byte 4 from a 0xf (SERVICE)
 			   to a 0x7 (SERVICE ACKNOWLEDGE) */
 			h->raw[h->crlen + 2] -= 0x8;
-			q931_xmit(ctrl, ctrl->tei, h, len, 1, 0);
+			q931_xmit(link, h, len, 1, 0);
 			return 0;
 		}
 		break;
@@ -6552,13 +6617,13 @@
 	}
 
 	cref = q931_cr(h);
-	c = q931_getcall(ctrl, cref);
+	c = q931_getcall(link, cref);
 	if (!c) {
 		pri_error(ctrl, "Unable to locate call %d\n", cref);
 		return -1;
 	}
-	if (c->master_call->outboundbroadcast && ctrl != PRI_MASTER(ctrl)) {
-		c = q931_get_subcall(ctrl, c->master_call);
+	if (c->master_call->outboundbroadcast && link != ctrl) {
+		c = q931_get_subcall(link, c->master_call);
 		if (!c) {
 			pri_error(ctrl, "Unable to locate subcall for %d\n", cref);
 			return -1;
@@ -6567,10 +6632,8 @@
 
 	if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
 		pri_message(ctrl,
-			"Received message for call %p on %p TEI/SAPI %d/%d, call->pri is %p TEI/SAPI %d/%d\n",
-			c,
-			ctrl, ctrl->tei, ctrl->sapi,
-			c->pri, c->pri->tei, c->pri->sapi);
+			"Received message for call %p on link %p TEI/SAPI %d/%d\n",
+			c, link, link->tei, link->sapi);
 	}
 
 	/* Preliminary handling */
@@ -8456,10 +8519,6 @@
 	struct q931_call *c = data;
 	struct pri *ctrl = c->pri;
 
-	/* Point to the master so the timeout event can come out. */
-	ctrl = PRI_MASTER(ctrl);
-	c->pri = ctrl;
-
 	if (ctrl->debug & PRI_DEBUG_Q931_STATE)
 		pri_message(ctrl, "T309 timed out waiting for data link re-establishment\n");
 
@@ -8475,10 +8534,6 @@
 	struct q931_call *c = data;
 	struct pri *ctrl = c->pri;
 
-	/* Point to the master so the timeout event can come out. */
-	ctrl = PRI_MASTER(ctrl);
-	c->pri = ctrl;
-
 	if (ctrl->debug & PRI_DEBUG_Q931_STATE)
 		pri_message(ctrl, "Cancel call after data link failure\n");
 
@@ -8549,11 +8604,6 @@
 	if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
 		pri_message(ctrl, "TEI=%d DL event: %s(%d)\n", link->tei,
 			q931_dl_event2str(event), event);
-	}
-
-	if (BRI_TE_PTMP(ctrl)) {
-		/* The link is always the master */
-		link = ctrl;
 	}
 
 	switch (event) {
@@ -8569,15 +8619,11 @@
 		 * removed TEI.
 		 */
 		for (cur = *ctrl->callpool; cur; cur = cur->next) {
-			if (!(cur->cr & ~Q931_CALL_REFERENCE_FLAG)) {
-				/* Don't do anything on the global call reference call record. */
-				continue;
-			}
 			if (cur->outboundbroadcast) {
 				/* Does this master call have a subcall on the link that went down? */
 				call = NULL;
 				for (idx = 0; idx < ARRAY_LEN(cur->subcalls); ++idx) {
-					if (cur->subcalls[idx] && cur->subcalls[idx]->pri == link) {
+					if (cur->subcalls[idx] && cur->subcalls[idx]->link == link) {
 						/* This subcall is on the link that went down. */
 						call = cur->subcalls[idx];
 						break;
@@ -8587,11 +8633,21 @@
 					/* No subcall is on the link that went down. */
 					continue;
 				}
-			} else if (cur->pri != link) {
+			} else if (cur->link != link) {
 				/* This call is not on the link that went down. */
 				continue;
 			} else {
 				call = cur;
+			}
+
+			if (!(cur->cr & ~Q931_CALL_REFERENCE_FLAG)) {
+				/* Simply destroy the global call reference call record. */
+				if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
+					pri_message(ctrl, "TEI=%d Destroying global call record\n",
+						link->tei);
+				}
+				q931_destroycall(ctrl, call);
+				continue;
 			}
 
 			/*
@@ -8605,7 +8661,7 @@
 					call->cr, call->channelno, call->ourcallstate,
 					q931_call_state_str(call->ourcallstate));
 			}
-			call->pri = ctrl;/* Point to a safer place until the call is destroyed. */
+			call->link = NULL;
 			pri_schedule_del(ctrl, call->retranstimer);
 			call->retranstimer = pri_schedule_event(ctrl, 0, pri_dl_down_cancelcall,
 				call);
@@ -8622,7 +8678,7 @@
 				/* Does this master call have a subcall on the link that went down? */
 				call = NULL;
 				for (idx = 0; idx < ARRAY_LEN(cur->subcalls); ++idx) {
-					if (cur->subcalls[idx] && cur->subcalls[idx]->pri == link) {
+					if (cur->subcalls[idx] && cur->subcalls[idx]->link == link) {
 						/* This subcall is on the link that went down. */
 						call = cur->subcalls[idx];
 						break;
@@ -8632,7 +8688,7 @@
 					/* No subcall is on the link that went down. */
 					continue;
 				}
-			} else if (cur->pri != link) {
+			} else if (cur->link != link) {
 				/* This call is not on the link that went down. */
 				continue;
 			} else {
@@ -8704,7 +8760,7 @@
 				/* Does this master call have a subcall on the link that came up? */
 				call = NULL;
 				for (idx = 0; idx < ARRAY_LEN(cur->subcalls); ++idx) {
-					if (cur->subcalls[idx] && cur->subcalls[idx]->pri == link) {
+					if (cur->subcalls[idx] && cur->subcalls[idx]->link == link) {
 						/* This subcall is on the link that came up. */
 						call = cur->subcalls[idx];
 						break;
@@ -8714,7 +8770,7 @@
 					/* No subcall is on the link that came up. */
 					continue;
 				}
-			} else if (cur->pri != link) {
+			} else if (cur->link != link) {
 				/* This call is not on the link that came up. */
 				continue;
 			} else {




More information about the svn-commits mailing list