[libpri-commits] mattf: trunk r429 - /trunk/

SVN commits to the libpri project libpri-commits at lists.digium.com
Tue Jun 19 15:31:55 CDT 2007


Author: mattf
Date: Tue Jun 19 15:31:54 2007
New Revision: 429

URL: http://svn.digium.com/view/libpri?view=rev&rev=429
Log:
Patch to add PTMP mode (BRI support)

Modified:
    trunk/Makefile
    trunk/libpri.h
    trunk/pri.c
    trunk/pri_internal.h
    trunk/pri_q921.h
    trunk/pri_timers.h
    trunk/prisched.c
    trunk/q921.c
    trunk/q931.c
    trunk/testprilib.c

Modified: trunk/Makefile
URL: http://svn.digium.com/view/libpri/trunk/Makefile?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/Makefile (original)
+++ trunk/Makefile Tue Jun 19 15:31:54 2007
@@ -39,7 +39,7 @@
 CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS)
 INSTALL_PREFIX=$(DESTDIR)
 INSTALL_BASE=/usr
-SOFLAGS = -Wl,-hlibpri.so.1.0
+SOFLAGS = -Wl,-h./libpri.so.1.0
 LDCONFIG = /sbin/ldconfig
 ifneq (,$(findstring X$(OSARCH)X, XLinuxX XGNU/kFreeBSDX))
 LDCONFIG_FLAGS=-n

Modified: trunk/libpri.h
URL: http://svn.digium.com/view/libpri/trunk/libpri.h?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/libpri.h (original)
+++ trunk/libpri.h Tue Jun 19 15:31:54 2007
@@ -257,20 +257,24 @@
 typedef struct pri_event_generic {
 	/* Events with no additional information fall in this category */
 	int e;
+	struct pri *pri;
 } pri_event_generic;
 
 typedef struct pri_event_error {
 	int e;
+	struct pri *pri;
 	char err[256];
 } pri_event_error;
 
 typedef struct pri_event_restart {
 	int e;
+	struct pri *pri;
 	int channel;
 } pri_event_restart;
 
 typedef struct pri_event_ringing {
 	int e;
+	struct pri *pri;
 	int channel;
 	int cref;
 	int progress;
@@ -281,6 +285,7 @@
 
 typedef struct pri_event_answer {
 	int e;
+	struct pri *pri;
 	int channel;
 	int cref;
 	int progress;
@@ -291,6 +296,7 @@
 
 typedef struct pri_event_facname {
 	int e;
+ 	struct pri *pri;
 	int callingpres;			/* Presentation of Calling CallerID */
 	int callingplan;			/* Dialing plan of Calling entity */
 	char callingname[256];
@@ -304,7 +310,9 @@
 #define PRI_CALLINGPLANRDNIS
 typedef struct pri_event_ring {
 	int e;
+	struct pri *pri;
 	int channel;				/* Channel requested */
+	int cref;					/* Call Reference Number */
 	int callingpres;			/* Presentation of Calling CallerID */
 	int callingplanani;			/* Dialing plan of Calling entity ANI */
 	int callingplan;			/* Dialing plan of Calling entity */
@@ -320,7 +328,6 @@
 	int callingplanrdnis;			/* Dialing plan of Redirecting Number */
 	char useruserinfo[260];		/* User->User info */
 	int flexible;				/* Are we flexible with our channel selection? */
-	int cref;					/* Call Reference Number */
 	int ctype;					/* Call type (see PRI_TRANS_CAP_* */
 	int layer1;					/* User layer 1 */
 	int complete;				/* Have we seen "Complete" i.e. no more number? */
@@ -336,9 +343,10 @@
 
 typedef struct pri_event_hangup {
 	int e;
+	struct pri *pri;
 	int channel;				/* Channel requested */
+	int cref;
 	int cause;
-	int cref;
 	q931_call *call;			/* Opaque call pointer */
 	long aoc_units;				/* Advise of Charge number of charged units */
 	char useruserinfo[260];		/* User->User info */
@@ -346,12 +354,14 @@
 
 typedef struct pri_event_restart_ack {
 	int e;
+	struct pri *pri;
 	int channel;
 } pri_event_restart_ack;
 
 #define PRI_PROGRESS_CAUSE
 typedef struct pri_event_proceeding {
 	int e;
+	struct pri *pri;
 	int channel;
 	int cref;
 	int progress;
@@ -362,18 +372,21 @@
  
 typedef struct pri_event_setup_ack {
 	int e;
+ 	struct pri *pri;
 	int channel;
 	q931_call *call;
 } pri_event_setup_ack;
 
 typedef struct pri_event_notify {
 	int e;
+ 	struct pri *pri;
 	int channel;
 	int info;
 } pri_event_notify;
 
 typedef struct pri_event_keypad_digit {
 	int e;
+ 	struct pri *pri;
 	int channel;
 	q931_call *call;
 	char digits[64];
@@ -408,6 +421,7 @@
    must be NON-BLOCKING! Frames received on the fd should include FCS.  Nodetype 
    must be one of PRI_NETWORK or PRI_CPE.  switchtype should be PRI_SWITCH_* */
 extern struct pri *pri_new(int fd, int nodetype, int switchtype);
+extern struct pri *pri_new_bri(int fd, int nodetype, int switchtype);
 
 /* Create D-channel just as above with user defined I/O callbacks and data */
 extern struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata);
@@ -602,7 +616,7 @@
 #define PRI_TIMER_N200	0	/* Maximum numer of q921 retransmissions */
 #define PRI_TIMER_N201	1	/* Maximum numer of octets in an information field */
 #define PRI_TIMER_N202	2	/* Maximum numer of transmissions of the TEI identity request message */
-#define PRI_TIMER_K	3	/* Maximum number of outstanding I-frames */
+#define PRI_TIMER_K		3	/* Maximum number of outstanding I-frames */
 
 #define PRI_TIMER_T200	4	/* time between SABME's */
 #define PRI_TIMER_T201	5	/* minimum time between retransmissions of the TEI Identity check messages */
@@ -630,4 +644,7 @@
 #define PRI_TIMER_T321	26
 #define PRI_TIMER_T322	27
 
+#define PRI_TIMER_TM20	28	/* maximum time avaiting XID response */
+#define PRI_TIMER_NM20	29	/* number of XID retransmits */
+
 #endif

Modified: trunk/pri.c
URL: http://svn.digium.com/view/libpri/trunk/pri.c?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/pri.c (original)
+++ trunk/pri.c Tue Jun 19 15:31:54 2007
@@ -187,7 +187,7 @@
 	return res;
 }
 
-static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata)
+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)
 {
 	struct pri *p;
 	p = malloc(sizeof(struct pri));
@@ -200,13 +200,19 @@
 		p->localtype = node;
 		p->switchtype = switchtype;
 		p->cref = 1;
-		p->sapi = Q921_SAPI_CALL_CTRL;
-		p->tei = 0;
+		p->sapi = (tei == Q921_TEI_GROUP) ? Q921_SAPI_LAYER2_MANAGEMENT : Q921_SAPI_CALL_CTRL;
+		p->tei = tei;
 		p->nsf = PRI_NSF_NONE;
 		p->protodisc = Q931_PROTOCOL_DISCRIMINATOR;
 		p->master = master;
 		p->callpool = &p->localpool;
+		p->ev.gen.pri = p;
 		pri_default_timers(p, switchtype);
+		if (master) {
+			pri_set_debug(p, master->debug);
+			if (master->sendfacility)
+				pri_facility_enable(p);
+		}
 #ifdef LIBPRI_COUNTERS
 		p->q921_rxcount = 0;
 		p->q921_txcount = 0;
@@ -217,7 +223,7 @@
 			p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
 			p->sapi = Q921_SAPI_GR303_EOC;
 			p->tei = Q921_TEI_GR303_EOC_OPS;
-			p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL);
+			p->subchannel = __pri_new_tei(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL, Q921_TEI_GR303_EOC_PATH);
 			if (!p->subchannel) {
 				free(p);
 				p = NULL;
@@ -226,7 +232,7 @@
 			p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
 			p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;
 			p->tei = Q921_TEI_GR303_TMC_CALLPROC;
-			p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL);
+			p->subchannel = __pri_new_tei(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL, Q921_TEI_GR303_TMC_SWITCHING);
 			if (!p->subchannel) {
 				free(p);
 				p = NULL;
@@ -270,7 +276,12 @@
 
 struct pri *pri_new(int fd, int nodetype, int switchtype)
 {
-	return __pri_new(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL);
+	return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_PRI);
+}
+
+struct pri *pri_new_bri(int fd, int nodetype, int switchtype)
+{
+	return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_GROUP);
 }
 
 struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata)
@@ -279,7 +290,7 @@
 		io_read = __pri_read;
 	if (!io_write)
 		io_write = __pri_write;
-	return __pri_new(fd, nodetype, switchtype, NULL, io_read, io_write, userdata);
+	return __pri_new_tei(fd, nodetype, switchtype, NULL, io_read, io_write, userdata, Q921_TEI_PRI);
 }
 
 void *pri_get_userdata(struct pri *pri)

Modified: trunk/pri_internal.h
URL: http://svn.digium.com/view/libpri/trunk/pri_internal.h?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/pri_internal.h (original)
+++ trunk/pri_internal.h Tue Jun 19 15:31:54 2007
@@ -83,6 +83,9 @@
 	/* Various timers */
 	int sabme_timer;	/* SABME retransmit */
 	int t203_timer;		/* Max idle time */
+	int t202_timer;
+	int n202_counter;
+	int ri;
 	int t200_timer;		/* T-200 retransmission timer */
 	/* All ISDN Timer values */
 	int timers[MAX_TIMERS];
@@ -265,4 +268,6 @@
 
 void libpri_copy_string(char *dst, const char *src, size_t size);
 
+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);
+
 #endif

Modified: trunk/pri_q921.h
URL: http://svn.digium.com/view/libpri/trunk/pri_q921.h?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/pri_q921.h (original)
+++ trunk/pri_q921.h Tue Jun 19 15:31:54 2007
@@ -46,10 +46,11 @@
 #define Q921_FRAMETYPE_I	0x0
 #define Q921_FRAMETYPE_S	0x1
 
-#define Q921_TEI_GROUP				127
+#define Q921_TEI_GROUP					127
+#define Q921_TEI_PRI					0
 #define Q921_TEI_GR303_EOC_PATH			0
 #define Q921_TEI_GR303_EOC_OPS			4
-#define Q921_TEI_GR303_TMC_SWITCHING		0
+#define Q921_TEI_GR303_TMC_SWITCHING	0
 #define Q921_TEI_GR303_TMC_CALLPROC		0
 
 #define Q921_SAPI_CALL_CTRL		0
@@ -62,6 +63,14 @@
 #define Q921_SAPI_X25_LAYER3      	16
 #define Q921_SAPI_LAYER2_MANAGEMENT	63
 
+
+#define Q921_TEI_IDENTITY_REQUEST			1
+#define Q921_TEI_IDENTITY_ASSIGNED			2
+#define Q921_TEI_IDENTITY_DENIED			3
+#define Q921_TEI_IDENTITY_CHECK_REQUEST		4
+#define Q921_TEI_IDENTITY_CHECK_RESPONSE	5
+#define Q921_TEI_IDENTITY_REMOVE			6
+#define Q921_TEI_IDENTITY_VERIFY			7
 
 typedef struct q921_header {
 #if __BYTE_ORDER == __BIG_ENDIAN
@@ -154,6 +163,12 @@
 #define Q921_INC(j) (j) = (((j) + 1) % 128)
 
 typedef enum q921_state {
+	Q921_DOWN,
+	Q921_TEI_UNASSIGNED,
+	Q921_TEI_AWAITING_ESTABLISH,
+	Q921_TEI_AWAITING_ASSIGN,
+	Q921_TEI_ASSIGNED,
+	Q921_NEGOTIATION,
 	Q921_LINK_CONNECTION_RELEASED,	/* Also known as TEI_ASSIGNED */
 	Q921_LINK_CONNECTION_ESTABLISHED,
 	Q921_AWAITING_ESTABLISH,

Modified: trunk/pri_timers.h
URL: http://svn.digium.com/view/libpri/trunk/pri_timers.h?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/pri_timers.h (original)
+++ trunk/pri_timers.h Tue Jun 19 15:31:54 2007
@@ -26,34 +26,37 @@
 #define _PRI_TIMERS_H
 
 /* -1 means we dont currently support the timer/counter */
-#define PRI_TIMERS_DEFAULT {	3,	/* N200 */ \
-				-1,	/* N201 */ \
-				-1,	/* N202 */ \
-				7,	/* K */ \
+#define PRI_TIMERS_DEFAULT { \
+				3,		/* N200 */ \
+				-1,		/* N201 */ \
+				3,		/* N202 */ \
+				7,		/* K */ \
 				1000,	/* T200 */ \
-				-1,	/* T201 */ \
-				-1,	/* T202 */ \
+				-1,		/* T201 */ \
+				10000,	/* T202 */ \
 				10000,	/* T203 */ \
-				-1,	/* T300 */ \
-				-1,	/* T301 */ \
-				-1,	/* T302 */ \
-				-1,	/* T303 */ \
-				-1,	/* T304 */ \
+				-1,		/* T300 */ \
+				-1,		/* T301 */ \
+				-1,		/* T302 */ \
+				-1,		/* T303 */ \
+				-1,		/* T304 */ \
 				30000,	/* T305 */ \
-				-1,	/* T306 */ \
-				-1,	/* T307 */ \
+				-1,		/* T306 */ \
+				-1,		/* T307 */ \
 				4000,	/* T308 */ \
-				-1,	/* T309 */ \
-				-1,	/* T310 */ \
+				-1,		/* T309 */ \
+				-1,		/* T310 */ \
 				4000,	/* T313 */ \
-				-1,	/* T314 */ \
-				-1,	/* T316 */ \
-				-1,	/* T317 */ \
-				-1,	/* T318 */ \
-				-1,	/* T319 */ \
-				-1,	/* T320 */ \
-				-1,	/* T321 */ \
-				-1	/* T322 */ \
+				-1,		/* T314 */ \
+				-1,		/* T316 */ \
+				-1,		/* T317 */ \
+				-1,		/* T318 */ \
+				-1,		/* T319 */ \
+				-1,		/* T320 */ \
+				-1,		/* T321 */ \
+				-1,		/* T322 */ \
+				2500,	/* TM20 - Q.921 Appendix IV */ \
+				3,		/* NM20 - Q.921 Appendix IV */ \
 			}
 
 /* XXX Only our default timers are setup now XXX */

Modified: trunk/prisched.c
URL: http://svn.digium.com/view/libpri/trunk/prisched.c?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/prisched.c (original)
+++ trunk/prisched.c Tue Jun 19 15:31:54 2007
@@ -35,6 +35,9 @@
 {
 	int x;
 	struct timeval tv;
+	/* Scheduling runs on master channels only */
+	while (pri->master)
+		pri = pri->master;
 	for (x=1;x<MAX_SCHED;x++)
 		if (!pri->pri_sched[x].callback)
 			break;
@@ -113,6 +116,8 @@
 
 void pri_schedule_del(struct pri *pri,int id)
 {
+	while (pri->master)
+		pri = pri->master;
 	if ((id >= MAX_SCHED) || (id < 0)) 
 		pri_error(pri, "Asked to delete sched id %d???\n", id);
 	pri->pri_sched[id].callback = NULL;

Modified: trunk/q921.c
URL: http://svn.digium.com/view/libpri/trunk/q921.c?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/q921.c (original)
+++ trunk/q921.c Tue Jun 19 15:31:54 2007
@@ -51,6 +51,7 @@
 } while(0)
 
 static void reschedule_t203(struct pri *pri);
+static void q921_restart(struct pri *pri, int now);
 
 static void q921_discard_retransmissions(struct pri *pri)
 {
@@ -92,6 +93,53 @@
 	}
 	reschedule_t203(pri);
 	return 0;
+}
+
+static void q921_send_tei(struct pri *pri, int message, int ri, int ai, int isreq)
+{
+	q921_u *f;
+
+	f = malloc(sizeof(*f) + 5);
+	if (f) {
+		memset(f, 0, sizeof(*f) + 5);
+		Q921_INIT(pri, *f);
+		f->h.c_r = isreq;
+		f->m3 = 0;
+		f->m2 = 0;
+		f->p_f = 0;
+		f->ft = Q921_FRAMETYPE_U;
+		f->data[0] = 0x0f;	/* Management entity */
+		f->data[1] = (ri >> 8) & 0xff;
+		f->data[2] = ri & 0xff;
+		f->data[3] = message;
+		f->data[4] = (ai << 1) | 1;
+//		if (pri->debug & PRI_DEBUG_Q921_STATE)
+			pri_message(pri, "Sending TEI management message %d, TEI=%d\n", message, ai);
+		q921_transmit(pri, (q921_h *)f, 8);
+		free(f);
+	}
+}
+
+static void q921_tei_request(void *vpri)
+{
+	struct pri *pri = (struct pri *)vpri;
+
+	if (pri->subchannel) {
+		pri_error(pri, "Cannot request TEI while its already assigned\n");
+		return;
+	}
+	pri->n202_counter++;
+#if 0
+	if (pri->n202_counter > pri->timers[PRI_TIMER_N202]) {
+		pri_error(pri, "Unable to assign TEI from network\n");
+		return;
+	}
+#endif
+	pri->ri = random() % 65535;
+	q921_send_tei(pri, Q921_TEI_IDENTITY_REQUEST, pri->ri, Q921_TEI_GROUP, 1);
+	if (pri->t202_timer)
+		pri_schedule_del(pri, pri->t202_timer);
+	pri->t202_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T202], q921_tei_request, pri);
 }
 
 static void q921_send_ua(struct pri *pri, int pfbit)
@@ -655,8 +703,10 @@
 	q921_reset(pri);
 	
 	/* Stop any SABME retransmissions */
-	pri_schedule_del(pri, pri->sabme_timer);
-	pri->sabme_timer = 0;
+	if (pri->sabme_timer) {
+		pri_schedule_del(pri, pri->sabme_timer);
+		pri->sabme_timer = 0;
+	}
 	
 	/* Reset any rejects */
 	pri->sentrej = 0;
@@ -699,9 +749,12 @@
 	pri->v_na = 0;
 	pri->window = pri->timers[PRI_TIMER_K];
 	pri->windowlen = 0;
-	pri_schedule_del(pri, pri->sabme_timer);
-	pri_schedule_del(pri, pri->t203_timer);
-	pri_schedule_del(pri, pri->t200_timer);
+	if (pri->sabme_timer)
+		pri_schedule_del(pri, pri->sabme_timer);
+	if (pri->t203_timer)
+		pri_schedule_del(pri, pri->t203_timer);
+	if (pri->t200_timer)
+		pri_schedule_del(pri, pri->t200_timer);
 	pri->sabme_timer = 0;
 	pri->t203_timer = 0;
 	pri->t200_timer = 0;
@@ -715,6 +768,66 @@
 	
 	/* Discard anything waiting to go out */
 	q921_discard_retransmissions(pri);
+}
+
+static pri_event *q921_receive_MDL(struct pri *pri, q921_u *h, int len)
+{
+	int ri;
+	struct pri *sub;
+	int tei;
+	pri_message(pri, "Received MDL message\n");
+	if (h->data[0] != 0x0f) {
+		pri_error(pri, "Received MDL with unsupported management entity %02x\n", h->data[0]);
+		return NULL;
+	}
+	if (!(h->data[4] & 0x01)) {
+		pri_error(pri, "Received MDL with multibyte TEI identifier\n");
+		return NULL;
+	}
+	ri = (h->data[1] << 8) | h->data[2];
+	tei = (h->data[4] >> 1);
+	switch(h->data[3]) {
+	case Q921_TEI_IDENTITY_REQUEST:
+		if (tei != 127) {
+			pri_error(pri, "Received TEI identity request with invalid TEI %d\n", tei);
+			q921_send_tei(pri, Q921_TEI_IDENTITY_DENIED, ri, tei, 0);
+		}
+		/* Go to master */
+		for (sub = pri; sub->master; sub = sub->master);
+		tei = 64;
+		while(sub->subchannel) {
+			if(sub->subchannel->tei == tei)
+				++tei;
+		}
+		sub->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei);
+		if (!sub->subchannel) {
+			pri_error(pri, "Unable to allocate D-channel for new TEI %d\n", tei);
+			return NULL;
+		}
+		q921_send_tei(pri, Q921_TEI_IDENTITY_ASSIGNED, ri, tei, 0);
+		break;
+	case Q921_TEI_IDENTITY_ASSIGNED:
+		if (ri != pri->ri) {
+			pri_message(pri, "TEI assignment received for invalid Ri %02x (our is %02x)\n", ri, pri->ri);
+			return NULL;
+		}
+		if (pri->t202_timer) {
+			pri_schedule_del(pri, pri->t202_timer);
+			pri->t202_timer = 0;
+		}
+		if (pri->subchannel) {
+			pri_error(pri, "TEI already assigned (new is %d, current is %d)\n", tei, pri->subchannel->tei);
+		}
+		pri_message(pri, "TEI assiged to %d\n", tei);
+		pri->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei);
+		if (!pri->subchannel) {
+			pri_error(pri, "Unable to allocate D-channel for new TEI %d\n", tei);
+			return NULL;
+		}
+		pri->q921_state = Q921_TEI_ASSIGNED;
+		break;
+	}
+	return NULL;	/* Do we need to return something??? */
 }
 
 static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
@@ -767,59 +880,59 @@
 				pri->solicitfbit = 0;
 			}
 			break;
-      case 1:
-         /* Receiver not ready */
-         if (pri->debug & PRI_DEBUG_Q921_DUMP)
-            pri_message(pri, "-- Got receiver not ready\n");
-	 if(h->s.p_f) {
-		/* Send RR if poll bit set */
-		q921_rr(pri, h->s.p_f, 0);
-	 }
-         pri->busy = 1;
-         break;   
-      case 2:
-         /* Just retransmit */
-         if (pri->debug & PRI_DEBUG_Q921_DUMP)
-            pri_message(pri, "-- Got reject requesting packet %d...  Retransmitting.\n", h->s.n_r);
-         if (h->s.p_f) {
-            /* If it has the poll bit set, send an appropriate supervisory response */
-            q921_rr(pri, 1, 0);
-         }
-		 sendnow = 0;
-         /* Resend the proper I-frame */
-         for(f=pri->txqueue;f;f=f->next) {
-               if ((sendnow || (f->h.n_s == h->s.n_r)) && f->transmitted) {
-                     /* Matches the request, or follows in our window, and has
-					    already been transmitted. */
-					 sendnow = 1;
-					 pri_error(pri, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);
-				     f->h.n_r = pri->v_r;
-                     q921_transmit(pri, (q921_h *)(&f->h), f->len);
-               }
-         }
-         if (!sendnow) {
-               if (pri->txqueue) {
-                     /* This should never happen */
-		     if (!h->s.p_f || h->s.n_r) {
-			pri_error(pri, "!! Got reject for frame %d, but we only have others!\n", h->s.n_r);
-		     }
-               } else {
-                     /* Hrm, we have nothing to send, but have been REJ'd.  Reset v_a, v_s, etc */
-				pri_error(pri, "!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
-                     pri->v_a = h->s.n_r;
-                     pri->v_s = h->s.n_r;
-                     /* Reset t200 timer if it was somehow going */
-                     if (pri->t200_timer) {
-                           pri_schedule_del(pri, pri->t200_timer);
-                           pri->t200_timer = 0;
-                     }
-                     /* Reset and restart t203 timer */
-                     if (pri->t203_timer)
-                           pri_schedule_del(pri, pri->t203_timer);
-                     pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
-               }
-         }
-         break;
+ 		case 1:
+ 			/* Receiver not ready */
+ 			if (pri->debug & PRI_DEBUG_Q921_STATE)
+ 				pri_message(pri, "-- Got receiver not ready\n");
+ 			if(h->s.p_f) {
+ 				/* Send RR if poll bit set */
+ 				q921_rr(pri, h->s.p_f, 0);
+ 			}
+ 			pri->busy = 1;
+ 			break;   
+ 		case 2:
+ 			/* Just retransmit */
+ 			if (pri->debug & PRI_DEBUG_Q921_STATE)
+ 				pri_message(pri, "-- Got reject requesting packet %d...  Retransmitting.\n", h->s.n_r);
+ 			if (h->s.p_f) {
+ 				/* If it has the poll bit set, send an appropriate supervisory response */
+ 				q921_rr(pri, 1, 0);
+ 			}
+ 			sendnow = 0;
+ 			/* Resend the proper I-frame */
+ 			for(f=pri->txqueue;f;f=f->next) {
+ 				if ((sendnow || (f->h.n_s == h->s.n_r)) && f->transmitted) {
+ 					/* Matches the request, or follows in our window, and has
+ 					   already been transmitted. */
+ 					sendnow = 1;
+ 					pri_error(pri, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);
+ 					f->h.n_r = pri->v_r;
+ 					q921_transmit(pri, (q921_h *)(&f->h), f->len);
+ 				}
+ 			}
+ 			if (!sendnow) {
+ 				if (pri->txqueue) {
+ 					/* This should never happen */
+ 					if (!h->s.p_f || h->s.n_r) {
+ 						pri_error(pri, "!! Got reject for frame %d, but we only have others!\n", h->s.n_r);
+ 					}
+ 				} else {
+ 					/* Hrm, we have nothing to send, but have been REJ'd.  Reset v_a, v_s, etc */
+ 					pri_error(pri, "!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
+ 					pri->v_a = h->s.n_r;
+ 					pri->v_s = h->s.n_r;
+ 					/* Reset t200 timer if it was somehow going */
+ 					if (pri->t200_timer) {
+ 						pri_schedule_del(pri, pri->t200_timer);
+ 						pri->t200_timer = 0;
+ 					}
+ 					/* Reset and restart t203 timer */
+ 					if (pri->t203_timer)
+ 						pri_schedule_del(pri, pri->t203_timer);
+ 					pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
+ 				}
+ 			}
+ 			break;
 		default:
 			pri_error(pri, "!! XXX Unknown Supervisory frame ss=0x%02x,pf=%02xnr=%02x vs=%02x, va=%02x XXX\n", h->s.ss, h->s.p_f, h->s.n_r,
 					pri->v_s, pri->v_a);
@@ -840,7 +953,7 @@
 						pri_message(pri, "-- Got DM Mode from peer.\n");
 					/* Disconnected mode, try again after T200 */
 					ev = q921_dchannel_down(pri);
-					q921_start(pri, 0);
+					q921_restart(pri, 0);
 					return ev;
 						
 				} else {
@@ -848,12 +961,15 @@
 						pri_message(pri, "-- Ignoring unsolicited DM with p/f set to 0\n");
 #if 0
 					/* Requesting that we start */
-					q921_start(pri, 0);
+					q921_restart(pri, 0);
 #endif					
 				}
 				break;
 			} else if (!h->u.m2) {
-				pri_message(pri, "XXX Unnumbered Information not implemented XXX\n");
+				if ((pri->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (pri->tei == Q921_TEI_GROUP))
+					q921_receive_MDL(pri, (q921_u *)h, len);
+				else
+					pri_message(pri, "XXX Unnumbered Information not implemented XXX\n");
 			}
 			break;
 		case 2:
@@ -862,7 +978,7 @@
 			/* Acknowledge */
 			q921_send_ua(pri, h->u.p_f);
 			ev = q921_dchannel_down(pri);
-			q921_start(pri, 0);
+			q921_restart(pri, 0);
 			return ev;
 		case 3:
 			if (h->u.m2 == 3) {
@@ -926,21 +1042,27 @@
 	if (h->h.ea1 || !(h->h.ea2))
 		return NULL;
 
+#if 0 /* Will be rejected by subchannel analyzis */
 	/* Check for broadcasts - not yet handled */
 	if (h->h.tei == Q921_TEI_GROUP)
 		return NULL;
+#endif
 
 	/* Check for SAPIs we don't yet handle */
 	if ((h->h.sapi != pri->sapi) || (h->h.tei != pri->tei)) {
-#ifdef PROCESS_SUBCHANNELS
+//#ifdef PROCESS_SUBCHANNELS
 		/* If it's not us, try any subchannels we have */
 		if (pri->subchannel)
 			return q921_receive(pri->subchannel, h, len + 2);
 		else 
-#endif
+//#endif
+		{
+			pri_error(pri, "Message for SAPI/TEI=%d/%d IS NOT HANDLED\n", h->h.sapi, h->h.tei);
 			return NULL;
-
-	}
+		}
+
+	}
+	pri_message(pri, "Handling message for SAPI/TEI=%d/%d\n", h->h.sapi, h->h.tei);
 	ev = __q921_receive_qualified(pri, h, len);
 	reschedule_t203(pri);
 	return ev;
@@ -956,7 +1078,7 @@
 	return e;
 }
 
-void q921_start(struct pri *pri, int now)
+static void q921_restart(struct pri *pri, int now)
 {
 	if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
 		pri_error(pri, "!! q921_start: Not in 'Link Connection Released' state\n");
@@ -967,3 +1089,17 @@
 	/* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
 	q921_send_sabme(pri, now);
 }
+
+void q921_start(struct pri *pri, int isCPE)
+{
+	q921_reset(pri);
+	if ((pri->sapi == Q921_SAPI_LAYER2_MANAGEMENT) && (pri->tei == Q921_TEI_GROUP)) {
+		pri_message(pri, "Starting in BRI mode\n");
+		pri->q921_state = Q921_DOWN;
+		if (isCPE)
+			q921_tei_request(pri);
+	} else {
+		pri_message(pri, "Starting in PRI mode, isCPE=%d, SAPI/TEI=%d/%d\n", isCPE, pri->sapi, pri->tei);
+		q921_send_sabme(pri, isCPE);
+	}
+}

Modified: trunk/q931.c
URL: http://svn.digium.com/view/libpri/trunk/q931.c?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/q931.c (original)
+++ trunk/q931.c Tue Jun 19 15:31:54 2007
@@ -2625,6 +2625,7 @@
 	return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
 }
 
+/* T313 expiry, first time */
 static void pri_connect_timeout(void *data)
 {
 	struct q931_call *c = data;
@@ -2635,6 +2636,7 @@
 	
 }
 
+/* T308 expiry, first time */
 static void pri_release_timeout(void *data)
 {
 	struct q931_call *c = data;
@@ -2643,9 +2645,12 @@
 		pri_message(pri, "Timed out looking for release complete\n");
 	c->t308_timedout++;
 	c->alive = 1;
-	q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);
-}
-
+
+	/* The call to q931_release will re-schedule T308 */
+	q931_release(pri, c, c->cause);
+}
+
+/* T308 expiry, second time */
 static void pri_release_finaltimeout(void *data)
 {
 	struct q931_call *c = data;
@@ -2667,6 +2672,7 @@
 	q931_hangup(pri, c, c->cause);
 }
 
+/* T305 expiry, first time */
 static void pri_disconnect_timeout(void *data)
 {
 	struct q931_call *c = data;

Modified: trunk/testprilib.c
URL: http://svn.digium.com/view/libpri/trunk/testprilib.c?view=diff&rev=429&r1=428&r2=429
==============================================================================
--- trunk/testprilib.c (original)
+++ trunk/testprilib.c Tue Jun 19 15:31:54 2007
@@ -64,7 +64,7 @@
 
 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
 
-#define TEST_CALLS 32
+#define TEST_CALLS 1
 
 static void event1(struct pri *pri, pri_event *e)
 {
@@ -232,9 +232,9 @@
 		}
 		if (e) {
 			if (first == pri) {
-				event1(pri, e);
+				event1(e->gen.pri, e);
 			} else {
-				event2(pri, e);
+				event2(e->gen.pri, e);
 			}
 		}
 		pthread_mutex_unlock(&lock);
@@ -254,7 +254,7 @@
 		perror("socketpair");
 		exit(1);
 	}
-	if (!(pri = pri_new(pair[0], PRI_NETWORK, PRI_DEF_SWITCHTYPE))) {
+	if (!(pri = pri_new_bri(pair[0], PRI_NETWORK, PRI_DEF_SWITCHTYPE))) {
 		perror("pri(0)");
 		exit(1);
 	}
@@ -265,7 +265,7 @@
 		perror("thread(0)");
 		exit(1);
 	}
-	if (!(pri = pri_new(pair[1], PRI_CPE, PRI_DEF_SWITCHTYPE))) {
+	if (!(pri = pri_new_bri(pair[1], PRI_CPE, PRI_DEF_SWITCHTYPE))) {
 		perror("pri(1)");
 		exit(1);
 	}




More information about the libpri-commits mailing list