[libpri-commits] dhubbard: branch dhubbard/issue3450 r550 - /team/dhubbard/issue3450/

SVN commits to the libpri project libpri-commits at lists.digium.com
Thu May 1 18:45:31 CDT 2008


Author: dhubbard
Date: Thu May  1 18:45:31 2008
New Revision: 550

URL: http://svn.digium.com/view/libpri?view=rev&rev=550
Log:
merged the latest mantis issue 3450 libpri patch.  The patch didn't apply cleanly, so hopefully my manual merge is correct

Modified:
    team/dhubbard/issue3450/libpri.h
    team/dhubbard/issue3450/pri.c
    team/dhubbard/issue3450/pri_internal.h
    team/dhubbard/issue3450/pri_q921.h
    team/dhubbard/issue3450/pri_q931.h
    team/dhubbard/issue3450/q921.c
    team/dhubbard/issue3450/q931.c

Modified: team/dhubbard/issue3450/libpri.h
URL: http://svn.digium.com/view/libpri/team/dhubbard/issue3450/libpri.h?view=diff&rev=550&r1=549&r2=550
==============================================================================
--- team/dhubbard/issue3450/libpri.h (original)
+++ team/dhubbard/issue3450/libpri.h Thu May  1 18:45:31 2008
@@ -76,6 +76,8 @@
 #define PRI_EVENT_NOTIFY		16	/* Notification received */
 #define PRI_EVENT_PROGRESS		17	/* When we get CALL_PROCEEDING or PROGRESS */
 #define PRI_EVENT_KEYPAD_DIGIT		18	/* When we receive during ACTIVE state */
+#define PRI_EVENT_SERVICE		19	/* NFAS Maintenance */
+#define PRI_EVENT_SERVICE_ACK		20	/* NFAS Maintenance */
 
 /* Simple states */
 #define PRI_STATE_DOWN		0
@@ -425,6 +427,18 @@
 	char digits[64];
 } pri_event_keypad_digit;
 
+typedef struct pri_event_service {
+	int e;
+	int channel;
+	int changestatus;
+} pri_event_service;
+
+typedef struct pri_event_service_ack {
+	int e;
+	int channel;
+	int changestatus;
+} pri_event_service_ack;
+
 typedef union {
 	int e;
 	pri_event_generic gen;		/* Generic view */
@@ -440,6 +454,8 @@
 	pri_event_setup_ack   setup_ack;	/* SETUP_ACKNOWLEDGE structure */
 	pri_event_notify notify;		/* Notification */
 	pri_event_keypad_digit digit;			/* Digits that come during a call */
+	pri_event_service service;		/* NFAS Maintenance */
+	pri_event_service_ack service_ack;	/* NFAS Maintenance */
 } pri_event;
 
 struct pri;
@@ -550,6 +566,9 @@
 int pri_restart(struct pri *pri);
 
 int pri_reset(struct pri *pri, int channel);
+
+/* Handle NFAS maintenance messages for putting B-Channels and D-Channels in and out of service  */
+extern int pri_maintenance_service(struct pri *pri, int span, int channel, int changestatus);
 
 /* Create a new call */
 q931_call *pri_new_call(struct pri *pri);

Modified: team/dhubbard/issue3450/pri.c
URL: http://svn.digium.com/view/libpri/team/dhubbard/issue3450/pri.c?view=diff&rev=550&r1=549&r2=550
==============================================================================
--- team/dhubbard/issue3450/pri.c (original)
+++ team/dhubbard/issue3450/pri.c Thu May  1 18:45:31 2008
@@ -608,6 +608,13 @@
 	return q931_restart(pri, channel);
 }
 
+int pri_maintenance_service(struct pri *pri, int span, int channel, int changestatus)
+{
+	if (!pri)
+		return -1;
+	return nfas_maintenance_service(pri, span, channel, changestatus);
+}
+
 q931_call *pri_new_call(struct pri *pri)
 {
 	if (!pri)

Modified: team/dhubbard/issue3450/pri_internal.h
URL: http://svn.digium.com/view/libpri/team/dhubbard/issue3450/pri_internal.h?view=diff&rev=550&r1=549&r2=550
==============================================================================
--- team/dhubbard/issue3450/pri_internal.h (original)
+++ team/dhubbard/issue3450/pri_internal.h Thu May  1 18:45:31 2008
@@ -255,6 +255,7 @@
 
 	/* Bridged call info */
 	q931_call *bridged_call;        /* Pointer to other leg of bridged call */
+	int changestatus;		/* NFAS Maintenance service related */
 };
 
 extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);

Modified: team/dhubbard/issue3450/pri_q921.h
URL: http://svn.digium.com/view/libpri/team/dhubbard/issue3450/pri_q921.h?view=diff&rev=550&r1=549&r2=550
==============================================================================
--- team/dhubbard/issue3450/pri_q921.h (original)
+++ team/dhubbard/issue3450/pri_q921.h Thu May  1 18:45:31 2008
@@ -187,4 +187,8 @@
 
 extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr);
 
+extern pri_event *q921_dchannel_up(struct pri *pri);
+
+extern pri_event *q921_dchannel_down(struct pri *pri);
+
 #endif

Modified: team/dhubbard/issue3450/pri_q931.h
URL: http://svn.digium.com/view/libpri/team/dhubbard/issue3450/pri_q931.h?view=diff&rev=550&r1=549&r2=550
==============================================================================
--- team/dhubbard/issue3450/pri_q931.h (original)
+++ team/dhubbard/issue3450/pri_q931.h Thu May  1 18:45:31 2008
@@ -108,6 +108,8 @@
 
 #define Q931_PROTOCOL_DISCRIMINATOR 0x08
 #define GR303_PROTOCOL_DISCRIMINATOR 0x4f
+#define NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR 0x3
+#define NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR_TOO 0x43
 
 /* Q.931 / National ISDN Message Types */
 
@@ -151,12 +153,9 @@
 #define Q931_SUSPEND_ACKNOWLEDGE	0x2d
 #define Q931_SUSPEND_REJECT			0x21
 
-/* Maintenance messages (codeset 0 only) */
-#define NATIONAL_SERVICE			0x0f
-#define NATIONAL_SERVICE_ACKNOWLEDGE	0x07
-
-/* Special codeset 0 IE */
-#define	NATIONAL_CHANGE_STATUS		0x1
+/* Maintenance messages (codeset 0) */
+#define NFAS_MAINTENANCE_SERVICE			0x0f
+#define NFAS_MAINTENANCE_SERVICE_ACKNOWLEDGE		0x07
 
 /* Q.931 / National ISDN Information Elements */
 #define Q931_LOCKING_SHIFT			0x90
@@ -218,6 +217,13 @@
 #define Q931_IE_USER_USER				0x7E
 #define Q931_IE_ESCAPE_FOR_EXT			0x7F
 
+/* For maintenance service */
+#define NFAS_IE_CHANGE_STATUS				0x01
+#define NFAS_CHANGE_STATUS_IN_SERVICE			0
+#define NFAS_CHANGE_STATUS_LOOP_BACK			1
+#define NFAS_CHANGE_STATUS_OUT_OF_SERVICE		2
+#define NFAS_CHANGE_STATUS_REQ_CONTINUITY_CHECK		3
+#define NFAS_CHANGE_STATUS_GRACEFUL_SHUTDOWN		4
 
 /* Call state stuff */
 #define Q931_CALL_STATE_NULL				0
@@ -243,6 +249,10 @@
 /* EuroISDN  */
 #define Q931_SENDING_COMPLETE		0xa1
 
+extern int nfas_maintenance_service(struct pri *pri, int span, int channel, int changestatus);
+
+extern int nfas_maintenance_service_ack(struct pri *pri, q931_call *call);
+
 
 /* Q.SIG specific */
 #define QSIG_IE_TRANSIT_COUNT		0x31

Modified: team/dhubbard/issue3450/q921.c
URL: http://svn.digium.com/view/libpri/team/dhubbard/issue3450/q921.c?view=diff&rev=550&r1=549&r2=550
==============================================================================
--- team/dhubbard/issue3450/q921.c (original)
+++ team/dhubbard/issue3450/q921.c Thu May  1 18:45:31 2008
@@ -258,7 +258,6 @@
 
 static void t203_expire(void *);
 static void t200_expire(void *);
-static pri_event *q921_dchannel_down(struct pri *pri);
 
 static void reschedule_t203(struct pri *pri)
 {
@@ -709,7 +708,7 @@
 	};
 }
 
-static pri_event *q921_dchannel_up(struct pri *pri)
+pri_event *q921_dchannel_up(struct pri *pri)
 {
 	/* Reset counters, etc */
 	q921_reset(pri);
@@ -739,7 +738,7 @@
 	return &pri->ev;
 }
 
-static pri_event *q921_dchannel_down(struct pri *pri)
+pri_event *q921_dchannel_down(struct pri *pri)
 {
 	/* Reset counters, reset sabme timer etc */
 	q921_reset(pri);

Modified: team/dhubbard/issue3450/q931.c
URL: http://svn.digium.com/view/libpri/team/dhubbard/issue3450/q931.c?view=diff&rev=550&r1=549&r2=550
==============================================================================
--- team/dhubbard/issue3450/q931.c (original)
+++ team/dhubbard/issue3450/q931.c Thu May  1 18:45:31 2008
@@ -84,10 +84,12 @@
 	{ Q931_SUSPEND, "SUSPEND" },
 	{ Q931_SUSPEND_ACKNOWLEDGE, "SUSPEND ACKNOWLEDGE" },
 	{ Q931_SUSPEND_REJECT, "SUSPEND REJECT" },
-
+};
+
+struct msgtype nfas_msgs[] = {
 	/* Maintenance */
-	{ NATIONAL_SERVICE, "SERVICE" },
-	{ NATIONAL_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE" },
+	{ NFAS_MAINTENANCE_SERVICE, "SERVICE", { Q931_CHANNEL_IDENT } },
+	{ NFAS_MAINTENANCE_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
 };
 
 static struct msgtype causes[] = {
@@ -379,7 +381,7 @@
 		return 0;
 	}
 
-	if (((pri->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit) {
+	if (((pri->switchtype != PRI_SWITCH_QSIG) && (call->ds1no >= 0)) || call->ds1explicit) {
 		/* Note that we are specifying the identifier */
 		ie->data[pos++] |= 0x40;
 		/* We need to use the Channel Identifier Present thingy.  Just specify it and we're done */
@@ -407,7 +409,7 @@
 			return pos + 2;
 		}
 	}
-	if (call->ds1no > 0) {
+	if (call->ds1no >= 0) {
 		/* We're done */
 		return pos + 2;
 	}
@@ -1162,6 +1164,27 @@
 	}
 
 	return 0;
+}
+
+static FUNC_DUMP(dump_change_status)
+{
+	int x;
+	pri_message(pri, "%c Change Status Information (len=%2d) [", prefix, len);
+	for (x=0;x<ie->len;x++)
+		pri_message(pri, " %02x", ie->data[x] & 0x7f);
+	pri_message(pri, " ]\n");
+}
+
+static FUNC_RECV(receive_change_status)
+{
+	call->changestatus = ie->data[0] & 0x0f;
+	return 0;
+}
+
+static FUNC_SEND(transmit_change_status)
+{
+	ie->data[0] = 0xc0 | call->changestatus;
+	return 3;
 }
 
 static char *prog2str(int prog)
@@ -2127,7 +2150,7 @@
 
 static struct ie ies[] = {
 	/* Codeset 0 - Common */
-	{ 1, NATIONAL_CHANGE_STATUS, "Change Status" },
+	{ 1, NFAS_IE_CHANGE_STATUS, "Change Status", dump_change_status, receive_change_status, transmit_change_status },
 	{ 0, Q931_LOCKING_SHIFT, "Locking Shift", dump_shift },
 	{ 0, Q931_BEARER_CAPABILITY, "Bearer Capability", dump_bearer_capability, receive_bearer_capability, transmit_bearer_capability },
 	{ 0, Q931_CAUSE, "Cause", dump_cause, receive_cause, transmit_cause },
@@ -2171,7 +2194,6 @@
 	{ 1, Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user, transmit_user_user },
 	{ 1, Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" },
 	{ 1, Q931_IE_CALL_STATUS, "Call Status" },
-	{ 1, Q931_IE_CHANGE_STATUS, "Change Status" },
 	{ 1, Q931_IE_CONNECTED_ADDR, "Connected Number", dump_connected_number },
 	{ 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number },
 	{ 1, Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number },
@@ -2185,7 +2207,7 @@
 	{ 1, Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility, transmit_facility },
 	{ 1, Q931_DISPLAY | Q931_CODESET(6), "Display (CS6)", dump_display, receive_display, transmit_display },
 	{ 0, Q931_IE_GENERIC_DIGITS, "Generic Digits", dump_generic_digits, receive_generic_digits, transmit_generic_digits },
-	/* Codeset 7 */
+	/* Codeset 7 - User specific */
 };
 
 static char *ie2str(int ie) 
@@ -2254,6 +2276,15 @@
 	for (x=0;x<sizeof(msgs) / sizeof(msgs[0]); x++) 
 		if (msgs[x].msgnum == msg)
 			return msgs[x].name;
+	return "Unknown Message Type";
+}
+
+static char *nfas_msg2str(int msg)
+{
+	unsigned int x;
+	for (x=0;x<sizeof(nfas_msgs) / sizeof(nfas_msgs[0]); x++)
+		if (nfas_msgs[x].msgnum == msg)
+			return nfas_msgs[x].name;
 	return "Unknown Message Type";
 }
 
@@ -2491,8 +2522,8 @@
 	static struct msgtype discs[] = {
 		{ Q931_PROTOCOL_DISCRIMINATOR, "Q.931" },
 		{ GR303_PROTOCOL_DISCRIMINATOR, "GR-303" },
-		{ 0x3, "AT&T Maintenance" },
-		{ 0x43, "New AT&T Maintenance" },
+		{ NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR, "AT&T Maintenance" },
+		{ NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR_TOO, "New AT&T Maintenance" },
 	};
 	return code2str(disc, discs, sizeof(discs) / sizeof(discs[0]));
 }
@@ -2509,7 +2540,11 @@
 	pri_message(pri, "%c Call Ref: len=%2d (reference %d/0x%X) (%s)\n", c, h->crlen, q931_cr(h) & 0x7FFF, q931_cr(h) & 0x7FFF, (h->crv[0] & 0x80) ? "Terminator" : "Originator");
 	/* Message header begins at the end of the call reference number */
 	mh = (q931_mh *)(h->contents + h->crlen);
-	pri_message(pri, "%c Message type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
+	/* Might be an NFAS message */
+	if ((h->pd == NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR) || (h->pd == NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR_TOO))
+		pri_message(pri, "%c Message type: %s (%d)\n", c, nfas_msg2str(mh->msg), mh->msg);
+	else
+		pri_message(pri, "%c Message type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
 	/* Drop length of header, including call reference */
 	len -= (h->crlen + 3);
 	codeset = cur_codeset = 0;
@@ -2555,12 +2590,15 @@
 	return -1;
 }
 
-static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len)
+static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len, int protodisc)
 {
 	/* Returns header and message header and modifies length in place */
 	q931_h *h = (q931_h *)buf;
 	q931_mh * mh;
-	h->pd = pri->protodisc;
+	if (protodisc)
+		h->pd = protodisc;
+	else
+		h->pd = pri->protodisc;
 	h->x0 = 0;		/* Reserved 0 */
 	if (!pri->bri) {
 		h->crlen = 2;	/* Two bytes of Call Reference.  Invert the top bit to make it from our sense */
@@ -2623,8 +2661,8 @@
 	
 	memset(buf, 0, sizeof(buf));
 	len = sizeof(buf);
-	init_header(pri, c, buf, &h, &mh, &len);
-	mh->msg = msgtype;
+	init_header(pri, c, buf, &h, &mh, &len, (msgtype >> 8));
+	mh->msg = msgtype & 0x00ff;
 	x=0;
 	codeset = 0;
 	while(ies[x] > -1) {
@@ -2644,6 +2682,29 @@
 	q931_xmit(c->pri, h, len, 1);
 	c->acked = 1;
 	return 0;
+}
+
+static int maintenance_service_ies[] = { NFAS_IE_CHANGE_STATUS, Q931_CHANNEL_IDENT, -1 };
+
+int nfas_maintenance_service_ack(struct pri *pri, q931_call *c)
+{
+	return send_message(pri, c, (NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR << 8) | NFAS_MAINTENANCE_SERVICE_ACKNOWLEDGE, maintenance_service_ies);
+}
+
+int nfas_maintenance_service(struct pri *pri, int span, int channel, int changestatus)
+{
+	struct q931_call *c;
+	c = q931_getcall(pri, 0 | 0x8000, 0);
+	if (!c)
+		return -1;
+	if (channel > -1) {
+		channel &= 0xff;
+	}
+	c->ds1no = span;
+	c->channelno = channel;
+	c->chanflags &= FLAG_EXCLUSIVE;
+	c->changestatus = changestatus;
+	return send_message(pri, c, (NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR << 8) | NFAS_MAINTENANCE_SERVICE, maintenance_service_ies);
 }
 
 static int status_ies[] = { Q931_CAUSE, Q931_CALL_STATE, -1 };
@@ -3241,14 +3302,7 @@
 	pri->q931_rxcount++;
 #endif
 	mh = (q931_mh *)(h->contents + h->crlen);
-	if ((h->pd == 0x3) || (h->pd == 0x43)) {
-		/* This is the weird maintenance stuff.  We majorly
-		   KLUDGE this by changing byte 4 from a 0xf (SERVICE) 
-		   to a 0x7 (SERVICE ACKNOWLEDGE) */
-		h->raw[h->crlen + 2] -= 0x8;
-		q931_xmit(pri, h, len, 1);
-		return 0;
-	} else if (h->pd != pri->protodisc) {
+	if ((h->pd != pri->protodisc) && (h->pd != NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR) && (h->pd != NFAS_MAINTENANCE_PROTOCOL_DISCRIMINATOR_TOO)) {
 		pri_error(pri, "Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd);
 		return 0;
 	}
@@ -3258,133 +3312,154 @@
 		return -1;
 	}
 	/* Preliminary handling */
-	switch(mh->msg) {
-	case Q931_RESTART:
-		if (pri->debug & PRI_DEBUG_Q931_STATE)
-			pri_message(pri, "-- Processing Q.931 Restart\n");
-		/* Reset information */
-		c->channelno = -1;
-		c->slotmap = -1;
-		c->chanflags = 0;
-		c->ds1no = 0;
-		c->ri = -1;
-		break;
-	case Q931_FACILITY:
-		c->callername[0] = '\0';
-		break;
-	case Q931_SETUP:
-		if (pri->debug & PRI_DEBUG_Q931_STATE)
-			pri_message(pri, "-- Processing Q.931 Call Setup\n");
-		c->channelno = -1;
-		c->slotmap = -1;
-		c->chanflags = 0;
-		c->ds1no = 0;
-		c->ri = -1;
-		c->transcapability = -1;
-		c->transmoderate = -1;
-		c->transmultiple = -1;
-		c->userl1 = -1;
-		c->userl2 = -1;
-		c->userl3 = -1;
-		c->rateadaption = -1;
-		c->calledplan = -1;
-		c->callerplan = -1;
-		c->callerpres = -1;
-		c->callernum[0] = '\0';
-		c->callednum[0] = '\0';
-		c->callername[0] = '\0';
-		c->callerani[0] = '\0';
-		c->callerplanani = -1;
-		c->redirectingplan = -1;
-		c->redirectingpres = -1;
-		c->redirectingreason = -1;
-		c->origcalledplan = -1;
-		c->origcalledpres = -1;
-		c->origredirectingreason = -1;
-		c->redirectingnum[0] = '\0';
-		c->origcallednum[0] = '\0';
-		c->redirectingname[0] = '\0';
-		c->origcalledname[0] = '\0';
-		c->useruserprotocoldisc = -1; 
-		c->useruserinfo[0] = '\0';
-		c->complete = 0;
-		c->nonisdn = 0;
-		c->aoc_units = -1;
-		/* Fall through */
-	case Q931_CONNECT:
-	case Q931_ALERTING:
-	case Q931_PROGRESS:
-		c->useruserinfo[0] = '\0';
-		c->cause = -1;
-		/* Fall through */
-	case Q931_CALL_PROCEEDING:
-		c->progress = -1;
-		c->progressmask = 0;
-		break;
-	case Q931_CONNECT_ACKNOWLEDGE:
-		if (c->retranstimer)
-			pri_schedule_del(pri, c->retranstimer);
-		c->retranstimer = 0;
-		break;
-	case Q931_RELEASE:
-	case Q931_DISCONNECT:
-		c->cause = -1;
-		c->causecode = -1;
-		c->causeloc = -1;
-		c->aoc_units = -1;
-		if (c->retranstimer)
-			pri_schedule_del(pri, c->retranstimer);
-		c->retranstimer = 0;
-		c->useruserinfo[0] = '\0';
-		break;
-	case Q931_RELEASE_COMPLETE:
-		if (c->retranstimer)
-			pri_schedule_del(pri, c->retranstimer);
-		c->retranstimer = 0;
-		c->useruserinfo[0] = '\0';
-		/* Fall through */
-	case Q931_STATUS:
-		c->cause = -1;
-		c->causecode = -1;
-		c->causeloc = -1;
-		c->sugcallstate = -1;
-		c->aoc_units = -1;
-		break;
-	case Q931_RESTART_ACKNOWLEDGE:
-		c->channelno = -1;
-		break;
-	case Q931_INFORMATION:
-		c->callednum[0] = '\0';
-		break;
-	case Q931_STATUS_ENQUIRY:
-		break;
-	case Q931_SETUP_ACKNOWLEDGE:
-		break;
-	case Q931_NOTIFY:
-		break;
-	case Q931_USER_INFORMATION:
-	case Q931_SEGMENT:
-	case Q931_CONGESTION_CONTROL:
-	case Q931_HOLD:
-	case Q931_HOLD_ACKNOWLEDGE:
-	case Q931_HOLD_REJECT:
-	case Q931_RETRIEVE:
-	case Q931_RETRIEVE_ACKNOWLEDGE:
-	case Q931_RETRIEVE_REJECT:
-	case Q931_RESUME:
-	case Q931_RESUME_ACKNOWLEDGE:
-	case Q931_RESUME_REJECT:
-	case Q931_SUSPEND:
-	case Q931_SUSPEND_ACKNOWLEDGE:
-	case Q931_SUSPEND_REJECT:
-		pri_error(pri, "!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
-		/* Fall through */
-	default:
-		pri_error(pri, "!! Don't know how to pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
-		q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
-		if (c->newcall) 
-			q931_destroycall(pri,c->cr);
-		return -1;
+	if (h->pd != pri->protodisc) {
+		/* Service messages are a superset of messages that can
+		 * take B-channels or entire D-channels in and out of service */
+		switch(mh->msg) {
+		case NFAS_MAINTENANCE_SERVICE:
+		case NFAS_MAINTENANCE_SERVICE_ACKNOWLEDGE:
+			c->channelno = -1;
+			c->slotmap = -1;
+			c->chanflags = 0;
+			c->ds1no = 0;
+			c->ri = -1;
+			c->changestatus = -1;
+			break;
+		default:
+			pri_error(pri, "!! Don't know how to pre-handle maintenance message type %s (%d)\n", nfas_msg2str(mh->msg), mh->msg);
+			return -1;
+			break;
+		}
+	} else {
+		/* All other messages*/
+		switch(mh->msg) {
+		case Q931_RESTART:
+			if (pri->debug & PRI_DEBUG_Q931_STATE)
+				pri_message(pri, "-- Processing Q.931 Restart\n");
+			/* Reset information */
+			c->channelno = -1;
+			c->slotmap = -1;
+			c->chanflags = 0;
+			c->ds1no = 0;
+			c->ri = -1;
+			break;
+		case Q931_FACILITY:
+			c->callername[0] = '\0';
+			break;
+		case Q931_SETUP:
+			if (pri->debug & PRI_DEBUG_Q931_STATE)
+				pri_message(pri, "-- Processing Q.931 Call Setup\n");
+			c->channelno = -1;
+			c->slotmap = -1;
+			c->chanflags = 0;
+			c->ds1no = 0;
+			c->ri = -1;
+			c->transcapability = -1;
+			c->transmoderate = -1;
+			c->transmultiple = -1;
+			c->userl1 = -1;
+			c->userl2 = -1;
+			c->userl3 = -1;
+			c->rateadaption = -1;
+			c->calledplan = -1;
+			c->callerplan = -1;
+			c->callerpres = -1;
+			c->callernum[0] = '\0';
+			c->callednum[0] = '\0';
+			c->callername[0] = '\0';
+			c->callerani[0] = '\0';
+			c->callerplanani = -1;
+			c->redirectingplan = -1;
+			c->redirectingpres = -1;
+			c->redirectingreason = -1;
+			c->origcalledplan = -1;
+			c->origcalledpres = -1;
+			c->origredirectingreason = -1;
+			c->redirectingnum[0] = '\0';
+			c->origcallednum[0] = '\0';
+			c->redirectingname[0] = '\0';
+			c->origcalledname[0] = '\0';
+			c->useruserprotocoldisc = -1; 
+			c->useruserinfo[0] = '\0';
+			c->complete = 0;
+			c->nonisdn = 0;
+			c->aoc_units = -1;
+			/* Fall through */
+		case Q931_CONNECT:
+		case Q931_ALERTING:
+		case Q931_PROGRESS:
+			c->useruserinfo[0] = '\0';
+			c->cause = -1;
+			/* Fall through */
+		case Q931_CALL_PROCEEDING:
+			c->progress = -1;
+			c->progressmask = 0;
+			break;
+		case Q931_CONNECT_ACKNOWLEDGE:
+			if (c->retranstimer)
+				pri_schedule_del(pri, c->retranstimer);
+			c->retranstimer = 0;
+			break;
+		case Q931_RELEASE:
+		case Q931_DISCONNECT:
+			c->cause = -1;
+			c->causecode = -1;
+			c->causeloc = -1;
+			c->aoc_units = -1;
+			if (c->retranstimer)
+				pri_schedule_del(pri, c->retranstimer);
+			c->retranstimer = 0;
+			c->useruserinfo[0] = '\0';
+			break;
+		case Q931_RELEASE_COMPLETE:
+			if (c->retranstimer)
+				pri_schedule_del(pri, c->retranstimer);
+			c->retranstimer = 0;
+			c->useruserinfo[0] = '\0';
+			/* Fall through */
+		case Q931_STATUS:
+			c->cause = -1;
+			c->causecode = -1;
+			c->causeloc = -1;
+			c->sugcallstate = -1;
+			c->aoc_units = -1;
+			break;
+		case Q931_RESTART_ACKNOWLEDGE:
+			c->channelno = -1;
+			break;
+		case Q931_INFORMATION:
+			c->callednum[0] = '\0';
+			break;
+		case Q931_STATUS_ENQUIRY:
+			break;
+		case Q931_SETUP_ACKNOWLEDGE:
+			break;
+		case Q931_NOTIFY:
+			break;
+		case Q931_USER_INFORMATION:
+		case Q931_SEGMENT:
+		case Q931_CONGESTION_CONTROL:
+		case Q931_HOLD:
+		case Q931_HOLD_ACKNOWLEDGE:
+		case Q931_HOLD_REJECT:
+		case Q931_RETRIEVE:
+		case Q931_RETRIEVE_ACKNOWLEDGE:
+		case Q931_RETRIEVE_REJECT:
+		case Q931_RESUME:
+		case Q931_RESUME_ACKNOWLEDGE:
+		case Q931_RESUME_REJECT:
+		case Q931_SUSPEND:
+		case Q931_SUSPEND_ACKNOWLEDGE:
+		case Q931_SUSPEND_REJECT:
+			pri_error(pri, "!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
+			/* Fall through */
+		default:
+			pri_error(pri, "!! Don't know how to pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
+			q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
+			if (c->newcall) 
+				q931_destroycall(pri,c->cr);
+			return -1;
+		}
 	}
 	/* Handle IEs */
 	memset(mandies, 0, sizeof(mandies));
@@ -3474,223 +3549,311 @@
 	}
 	
 	/* Post handling */
-	switch(mh->msg) {
-	case Q931_RESTART:
-		if (missingmand) {
-			q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
-			q931_destroycall(pri, c->cr);
+ 	if (h->pd != pri->protodisc) {
+ 		/* Do the maintenance stuff */
+ 		switch(mh->msg) {
+ 		case NFAS_MAINTENANCE_SERVICE:
+ 			if (c->channelno > 0) {
+ 				pri->ev.e = PRI_EVENT_SERVICE;
+ 				pri->ev.service.channel = c->channelno | (c->ds1no << 8);
+ 				pri->ev.service.changestatus = 0x0f & c->changestatus;
+ 			} else {
+ 				switch (0x0f & c->changestatus) {
+ 				case NFAS_CHANGE_STATUS_IN_SERVICE:
+ 					pri->ev.e = PRI_EVENT_DCHAN_UP;
+ 					q921_dchannel_up(pri);
+ 					break;
+ 				case NFAS_CHANGE_STATUS_OUT_OF_SERVICE:
+ 				case NFAS_CHANGE_STATUS_LOOP_BACK:
+ 				case NFAS_CHANGE_STATUS_REQ_CONTINUITY_CHECK:
+ 				case NFAS_CHANGE_STATUS_GRACEFUL_SHUTDOWN:
+ 					pri->ev.e = PRI_EVENT_DCHAN_DOWN;
+ 					q921_dchannel_down(pri);
+ 					break;
+ 				default:
+ 					pri_error(pri, "!! Don't know how to handle span service change status %d\n", (0x0f & c->changestatus));
+ 					return -1;
+ 					break;
+ 				}
+ 			}
+ 			nfas_maintenance_service_ack(pri, c);
+ 			return Q931_RES_HAVEEVENT;
+ 		case NFAS_MAINTENANCE_SERVICE_ACKNOWLEDGE:
+ 			if (c->channelno > 0) {
+ 				pri->ev.e = PRI_EVENT_SERVICE_ACK;
+ 				pri->ev.service_ack.channel = c->channelno | (c->ds1no << 8);
+ 				pri->ev.service_ack.changestatus = 0x0f & c->changestatus;
+ 			} else {
+ 				switch (0x0f & c->changestatus) {
+ 				case NFAS_CHANGE_STATUS_IN_SERVICE:
+ 					pri->ev.e = PRI_EVENT_DCHAN_UP;
+ 					q921_dchannel_up(pri);
+ 					break;
+ 				case NFAS_CHANGE_STATUS_OUT_OF_SERVICE:
+ 				case NFAS_CHANGE_STATUS_LOOP_BACK:
+ 				case NFAS_CHANGE_STATUS_REQ_CONTINUITY_CHECK:
+ 				case NFAS_CHANGE_STATUS_GRACEFUL_SHUTDOWN:
+ 					pri->ev.e = PRI_EVENT_DCHAN_DOWN;
+ 					q921_dchannel_down(pri);
+ 					break;
+ 				default:
+ 					pri_error(pri, "!! Don't know how to handle span service change status %d\n", (0x0f & c->changestatus));
+ 					return -1;
+					break;
+				}
+			}
+			return Q931_RES_HAVEEVENT;
+		default:
+			pri_error(pri, "!! Don't know how to post-handle maintenance message type %s (%d)\n", nfas_msg2str(mh->msg), mh->msg);
+			return -1;
 			break;
 		}
-		UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_RESTART);
-		c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST;
-		/* Send back the Restart Acknowledge */
-		restart_ack(pri, c);
-		/* Notify user of restart event */
-		pri->ev.e = PRI_EVENT_RESTART;
-		pri->ev.restart.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-		return Q931_RES_HAVEEVENT;
-	case Q931_SETUP:
-		if (missingmand) {
-			q931_release_complete(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
+	} else {
+		/* Do the non-maintenance stuff */
+		switch(mh->msg) {
+		case Q931_RESTART:
+			if (missingmand) {
+				q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
+				q931_destroycall(pri, c->cr);
+				break;
+			}
+			UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_RESTART);
+			c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST;
+			/* Send back the Restart Acknowledge */
+			restart_ack(pri, c);
+			/* Notify user of restart event */
+			pri->ev.e = PRI_EVENT_RESTART;
+			pri->ev.restart.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+			return Q931_RES_HAVEEVENT;
+		case Q931_SETUP:
+			if (missingmand) {
+				q931_release_complete(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
+				break;
+			}
+			/* Must be new call */
+			if (!c->newcall) {
+				break;
+			}
+			if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN)
+			c->nonisdn = 1;
+			c->newcall = 0;
+			UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_PRESENT);
+			c->peercallstate = Q931_CALL_STATE_CALL_INITIATED;
+			/* it's not yet a call since higher level can respond with RELEASE or RELEASE_COMPLETE */
+			c->alive = 0;
+			if (c->transmoderate != TRANS_MODE_64_CIRCUIT) {
+				q931_release_complete(pri, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL);
+				break;
+			}
+			pri->ev.e = PRI_EVENT_RING;
+			pri->ev.ring.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+			pri->ev.ring.callingpres = c->callerpres;
+			pri->ev.ring.callingplan = c->callerplan;
+			pri->ev.ring.callingplanani = c->callerplanani;
+			pri->ev.ring.callingplanrdnis = c->redirectingplan;
+			pri->ev.ring.callingplanorigcalled = c->origcalledplan;
+			pri->ev.ring.ani2 = c->ani2;
+			libpri_copy_string(pri->ev.ring.callingani, c->callerani, sizeof(pri->ev.ring.callingani));
+			libpri_copy_string(pri->ev.ring.callingnum, c->callernum, sizeof(pri->ev.ring.callingnum));
+			libpri_copy_string(pri->ev.ring.callingname, c->callername, sizeof(pri->ev.ring.callingname));
+			pri->ev.ring.calledplan = c->calledplan;
+			libpri_copy_string(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr));
+			libpri_copy_string(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum));
+			libpri_copy_string(pri->ev.ring.origcalledname, c->origcalledname, sizeof(pri->ev.ring.origcalledname));
+			libpri_copy_string(pri->ev.ring.origcallednum, c->origcallednum, sizeof(pri->ev.ring.origcallednum));
+			libpri_copy_string(pri->ev.ring.redirectingnum, c->redirectingnum, sizeof(pri->ev.ring.redirectingnum));
+			libpri_copy_string(pri->ev.ring.redirectingname, c->redirectingname, sizeof(pri->ev.ring.redirectingname));
+			libpri_copy_string(pri->ev.ring.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo));
+			c->useruserinfo[0] = '\0';
+			pri->ev.ring.redirectingreason = c->redirectingreason;
+			pri->ev.ring.origredirectingreason = c->origredirectingreason;
+			pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE);
+			pri->ev.ring.cref = c->cr;
+			pri->ev.ring.call = c;
+			pri->ev.ring.layer1 = c->userl1;
+			pri->ev.ring.complete = c->complete; 
+			pri->ev.ring.ctype = c->transcapability;
+			pri->ev.ring.redirectingreason = c->redirectingreason;
+			pri->ev.ring.progress = c->progress;
+			pri->ev.ring.progressmask = c->progressmask;
+			return Q931_RES_HAVEEVENT;
+		case Q931_ALERTING:
+			if (c->newcall) {
+				q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
+				break;
+			}
+			UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_DELIVERED);
+			c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
+			pri->ev.e = PRI_EVENT_RINGING;
+			pri->ev.ringing.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+			pri->ev.ringing.cref = c->cr;
+			pri->ev.ringing.call = c;
+			pri->ev.ringing.progress = c->progress;
+			pri->ev.ringing.progressmask = c->progressmask;
+			libpri_copy_string(pri->ev.ringing.useruserinfo, c->useruserinfo, sizeof(pri->ev.ringing.useruserinfo));
+			c->useruserinfo[0] = '\0';
+	
+			cur = c->apdus;
+			while (cur) {
+				if (!cur->sent && cur->message == Q931_FACILITY) {
+					q931_facility(pri, c);
+					break;
+				}
+				cur = cur->next;
+			}
+	
+			return Q931_RES_HAVEEVENT;
+		case Q931_CONNECT:
+			if (c->newcall) {
+				q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
+				break;
+			}
+			if (c->ourcallstate == Q931_CALL_STATE_ACTIVE) {
+				q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE);
+				break;
+			}
+			UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE);
+			c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
+			pri->ev.e = PRI_EVENT_ANSWER;
+			pri->ev.answer.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+			pri->ev.answer.cref = c->cr;
+			pri->ev.answer.call = c;
+			pri->ev.answer.progress = c->progress;
+			pri->ev.answer.progressmask = c->progressmask;
+			libpri_copy_string(pri->ev.answer.useruserinfo, c->useruserinfo, sizeof(pri->ev.answer.useruserinfo));
+			c->useruserinfo[0] = '\0';
+			q931_connect_acknowledge(pri, c);
+			if (c->justsignalling) {  /* Make sure WE release when we initiatie a signalling only connection */
+				q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);
+				break;
+			} else
+				return Q931_RES_HAVEEVENT;
+		case Q931_FACILITY:
+			if (c->newcall) {
+				q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
+				break;
+			}
+			pri->ev.e = PRI_EVENT_FACNAME;
+			libpri_copy_string(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname));
+			libpri_copy_string(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingnum));
+			pri->ev.facname.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+			pri->ev.facname.callingpres = c->callerpres;
+			pri->ev.facname.callingplan = c->callerplan;
+			pri->ev.facname.cref = c->cr;
+			pri->ev.facname.call = c;
+#if 0	
+			pri_message(pri, "Sending facility event (%s/%s)\n", pri->ev.facname.callingname, pri->ev.facname.callingnum);
+#endif
+			return Q931_RES_HAVEEVENT;
+		case Q931_PROGRESS:
+			if (missingmand) {
+				q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
+				q931_destroycall(pri, c->cr);
+				break;
+			}
+			pri->ev.e = PRI_EVENT_PROGRESS;
+			pri->ev.proceeding.cause = c->cause;
+			/* Fall through */
+		case Q931_CALL_PROCEEDING:
+			if (c->newcall) {
+				q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
+				break;
+			}
+			if ((c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED) &&
+			    (c->ourcallstate != Q931_CALL_STATE_OVERLAP_SENDING) && 
+			    (c->ourcallstate != Q931_CALL_STATE_CALL_DELIVERED) && 
+			    (c->ourcallstate != Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING)) {
+				q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE);
+				break;
+			}
+			pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+			if (mh->msg == Q931_CALL_PROCEEDING) {
+				pri->ev.e = PRI_EVENT_PROCEEDING;
+				UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING);
+				c->peercallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING;
+			}
+			pri->ev.proceeding.progress = c->progress;
+			pri->ev.proceeding.progressmask = c->progressmask;
+			pri->ev.proceeding.cref = c->cr;
+			pri->ev.proceeding.call = c;
+	
+			cur = c->apdus;
+			while (cur) {
+				if (!cur->sent && cur->message == Q931_FACILITY) {
+					q931_facility(pri, c);
+					break;
+				}
+				cur = cur->next;
+			}
+			return Q931_RES_HAVEEVENT;
+		case Q931_CONNECT_ACKNOWLEDGE:
+			if (c->newcall) {
+				q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
+				break;
+			}
+			if (!(c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) &&
+			    !(c->ourcallstate == Q931_CALL_STATE_ACTIVE &&
+			      (pri->localtype == PRI_NETWORK || pri->switchtype == PRI_SWITCH_QSIG))) {
+				q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE);
+				break;
+			}
+			UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE);
+			c->peercallstate = Q931_CALL_STATE_ACTIVE;
 			break;
-		}
-		/* Must be new call */
-		if (!c->newcall) {
+		case Q931_STATUS:
+			if (missingmand) {
+				q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
+				q931_destroycall(pri, c->cr);
+				break;
+			}
+			if (c->newcall) {
+				if (c->cr & 0x7fff)
+					q931_release_complete(pri,c,PRI_CAUSE_WRONG_CALL_STATE);
+				break;	
+			}
+			/* Do nothing */
+			/* Also when the STATUS asks for the call of an unexisting reference send RELEASE_COMPL */
+			if ((pri->debug & PRI_DEBUG_Q931_ANOMALY) &&
+			    (c->cause != PRI_CAUSE_INTERWORKING)) 
+				pri_error(pri, "Received unsolicited status: %s\n", pri_cause2str(c->cause));
+			/* Workaround for S-12 ver 7.3 - it responds for invalid/non-implemented IEs at SETUP with null call state */
+			if (!c->sugcallstate && (c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED)) {
+				pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+				pri->ev.hangup.cause = c->cause;
+				pri->ev.hangup.cref = c->cr;
+				pri->ev.hangup.call = c;
+				pri->ev.hangup.aoc_units = c->aoc_units;
+				libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
+				/* Free resources */
+				UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
+				c->peercallstate = Q931_CALL_STATE_NULL;
+				if (c->alive) {
+					pri->ev.e = PRI_EVENT_HANGUP;
+					res = Q931_RES_HAVEEVENT;
+					c->alive = 0;
+				} else if (c->sendhangupack) {
+					res = Q931_RES_HAVEEVENT;
+					pri->ev.e = PRI_EVENT_HANGUP_ACK;
+					q931_hangup(pri, c, c->cause);
+				} else {
+					q931_hangup(pri, c, c->cause);
+					res = 0;
+				}	
+				if (res)
+					return res;
+			}
 			break;
-		}
-		if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN)
-			c->nonisdn = 1;
-		c->newcall = 0;
-		UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_PRESENT);
-		c->peercallstate = Q931_CALL_STATE_CALL_INITIATED;
-		/* it's not yet a call since higher level can respond with RELEASE or RELEASE_COMPLETE */
-		c->alive = 0;
-		if (c->transmoderate != TRANS_MODE_64_CIRCUIT) {
-			q931_release_complete(pri, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL);
-			break;
-		}
-		pri->ev.e = PRI_EVENT_RING;
-		pri->ev.ring.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-		pri->ev.ring.callingpres = c->callerpres;
-		pri->ev.ring.callingplan = c->callerplan;
-		pri->ev.ring.callingplanani = c->callerplanani;
-		pri->ev.ring.callingplanrdnis = c->redirectingplan;
-		pri->ev.ring.callingplanorigcalled = c->origcalledplan;
-		pri->ev.ring.ani2 = c->ani2;
-		libpri_copy_string(pri->ev.ring.callingani, c->callerani, sizeof(pri->ev.ring.callingani));
-		libpri_copy_string(pri->ev.ring.callingnum, c->callernum, sizeof(pri->ev.ring.callingnum));
-		libpri_copy_string(pri->ev.ring.callingname, c->callername, sizeof(pri->ev.ring.callingname));
-		pri->ev.ring.calledplan = c->calledplan;
-		libpri_copy_string(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr));
-		libpri_copy_string(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum));
-		libpri_copy_string(pri->ev.ring.origcalledname, c->origcalledname, sizeof(pri->ev.ring.origcalledname));
-		libpri_copy_string(pri->ev.ring.origcallednum, c->origcallednum, sizeof(pri->ev.ring.origcallednum));
-		libpri_copy_string(pri->ev.ring.redirectingnum, c->redirectingnum, sizeof(pri->ev.ring.redirectingnum));
-		libpri_copy_string(pri->ev.ring.redirectingname, c->redirectingname, sizeof(pri->ev.ring.redirectingname));
-		libpri_copy_string(pri->ev.ring.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo));
-		c->useruserinfo[0] = '\0';
-		pri->ev.ring.redirectingreason = c->redirectingreason;
-		pri->ev.ring.origredirectingreason = c->origredirectingreason;
-		pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE);
-		pri->ev.ring.cref = c->cr;
-		pri->ev.ring.call = c;
-		pri->ev.ring.layer1 = c->userl1;
-		pri->ev.ring.complete = c->complete; 
-		pri->ev.ring.ctype = c->transcapability;
-		pri->ev.ring.redirectingreason = c->redirectingreason;
-		pri->ev.ring.progress = c->progress;
-		pri->ev.ring.progressmask = c->progressmask;
-		return Q931_RES_HAVEEVENT;
-	case Q931_ALERTING:
-		if (c->newcall) {
-			q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-			break;
-		}
-		UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_DELIVERED);
-		c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
-		pri->ev.e = PRI_EVENT_RINGING;
-		pri->ev.ringing.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-		pri->ev.ringing.cref = c->cr;
-		pri->ev.ringing.call = c;
-		pri->ev.ringing.progress = c->progress;
-		pri->ev.ringing.progressmask = c->progressmask;
-		libpri_copy_string(pri->ev.ringing.useruserinfo, c->useruserinfo, sizeof(pri->ev.ringing.useruserinfo));
-		c->useruserinfo[0] = '\0';
-
-		cur = c->apdus;
-		while (cur) {
-			if (!cur->sent && cur->message == Q931_FACILITY) {
-				q931_facility(pri, c);
-				break;
-			}
-			cur = cur->next;
-		}
-
-		return Q931_RES_HAVEEVENT;
-	case Q931_CONNECT:
-		if (c->newcall) {
-			q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-			break;
-		}
-		if (c->ourcallstate == Q931_CALL_STATE_ACTIVE) {
-			q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE);
-			break;
-		}
-		UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE);
-		c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
-		pri->ev.e = PRI_EVENT_ANSWER;
-		pri->ev.answer.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-		pri->ev.answer.cref = c->cr;
-		pri->ev.answer.call = c;
-		pri->ev.answer.progress = c->progress;
-		pri->ev.answer.progressmask = c->progressmask;
-		libpri_copy_string(pri->ev.answer.useruserinfo, c->useruserinfo, sizeof(pri->ev.answer.useruserinfo));
-		c->useruserinfo[0] = '\0';
-		q931_connect_acknowledge(pri, c);
-		if (c->justsignalling) {  /* Make sure WE release when we initiatie a signalling only connection */
-			q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);
-			break;
-		} else
-			return Q931_RES_HAVEEVENT;
-	case Q931_FACILITY:
-		if (c->newcall) {
-			q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-			break;
-		}
-		pri->ev.e = PRI_EVENT_FACNAME;
-		libpri_copy_string(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname));
-		libpri_copy_string(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingnum));
-		pri->ev.facname.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-		pri->ev.facname.callingpres = c->callerpres;
-		pri->ev.facname.callingplan = c->callerplan;
-		pri->ev.facname.cref = c->cr;
-		pri->ev.facname.call = c;
-#if 0
-		pri_message(pri, "Sending facility event (%s/%s)\n", pri->ev.facname.callingname, pri->ev.facname.callingnum);
-#endif
-		return Q931_RES_HAVEEVENT;
-	case Q931_PROGRESS:
-		if (missingmand) {
-			q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
-			q931_destroycall(pri, c->cr);
-			break;
-		}
-		pri->ev.e = PRI_EVENT_PROGRESS;
-		pri->ev.proceeding.cause = c->cause;
-		/* Fall through */
-	case Q931_CALL_PROCEEDING:
-		if (c->newcall) {
-			q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-			break;
-		}

[... 407 lines stripped ...]



More information about the libpri-commits mailing list