[libpri-commits] rmudgett: branch 1.4 r1051 - in /branches/1.4: libpri.h q931.c
SVN commits to the libpri project
libpri-commits at lists.digium.com
Mon Aug 31 17:58:02 CDT 2009
Author: rmudgett
Date: Mon Aug 31 17:57:58 2009
New Revision: 1051
URL: http://svn.asterisk.org/svn-view/libpri?view=rev&rev=1051
Log:
Make event channel parameter encoding consistent.
Also make sure that service maintenance messages have the channel id
parameters reinitialized for each message since they are sent over the
global call reference.
Modified:
branches/1.4/libpri.h
branches/1.4/q931.c
Modified: branches/1.4/libpri.h
URL: http://svn.asterisk.org/svn-view/libpri/branches/1.4/libpri.h?view=diff&rev=1051&r1=1050&r2=1051
==============================================================================
--- branches/1.4/libpri.h (original)
+++ branches/1.4/libpri.h Mon Aug 31 17:57:58 2009
@@ -493,6 +493,25 @@
};
+/*
+ * Event channel parameter encoding:
+ * 3322 2222 2222 1111 1111 1100 0000 0000
+ * 1098 7654 3210 9876 5432 1098 7654 3210
+ * xxxx xxxx xxxx xxDC BBBBBBBBB AAAAAAAAA
+ *
+ * Bit field
+ * A - B channel
+ * B - Span (DS1) (0 - 127)
+ * C - DS1 Explicit bit
+ * D - D channel (cis_call) bit (status only)
+ *
+ * B channel values:
+ * 0 - No channel (ISDN uses for call waiting feature)
+ * 1-127 - B channel #
+ * 0xFF - Any channel (Also if whole channel value is -1 in event)
+ */
+
+
typedef struct pri_event_generic {
/* Events with no additional information fall in this category */
int e;
Modified: branches/1.4/q931.c
URL: http://svn.asterisk.org/svn-view/libpri/branches/1.4/q931.c?view=diff&rev=1051&r1=1050&r2=1051
==============================================================================
--- branches/1.4/q931.c (original)
+++ branches/1.4/q931.c Mon Aug 31 17:57:58 2009
@@ -167,8 +167,9 @@
{ PRI_NSF_CALL_REDIRECTION_SERVICE, "Call Redirection Service" }
};
-#define FLAG_PREFERRED 2
-#define FLAG_EXCLUSIVE 4
+#define FLAG_WHOLE_INTERFACE 0x01
+#define FLAG_PREFERRED 0x02
+#define FLAG_EXCLUSIVE 0x04
#define RESET_INDICATOR_CHANNEL 0
#define RESET_INDICATOR_DS1 6
@@ -254,6 +255,20 @@
};
/*!
+ * \internal
+ * \brief Encode the channel id information to pass to upper level.
+ *
+ * \param call Q.931 call leg
+ *
+ * \return Encoded channel value.
+ */
+static int q931_encode_channel(const q931_call *call)
+{
+ return call->channelno | (call->ds1no << 8) | (call->ds1explicit << 16)
+ | (call->cis_call << 17);
+}
+
+/*!
* \brief Determine if layer 2 is in PTMP mode.
*
* \param ctrl D channel controller.
@@ -640,48 +655,77 @@
static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
{
int x;
- int pos=0;
-#ifdef NO_BRI_SUPPORT
- if (!ie->data[0] & 0x20) {
- pri_error(ctrl, "!! Not PRI type!?\n");
- return -1;
- }
-#endif
-#ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
- if (ctrl->bri) {
- if (!(ie->data[0] & 3))
- call->cis_call = 1;
- else
- call->channelno = ie->data[0] & 3;
+ int pos = 0;
+ int need_extended_channel_octets;/*!< TRUE if octets 3.2 and 3.3 need to be present. */
+
+ if (ie->data[0] & 0x08) {
+ call->chanflags = FLAG_EXCLUSIVE;
} else {
- switch (ie->data[0] & 3) {
- case 0:
- call->cis_call = 1;
- break;
- case 1:
- break;
- default:
- pri_error(ctrl, "!! Unexpected Channel selection %d\n", ie->data[0] & 3);
- return -1;
- }
- }
-#endif
- if (ie->data[0] & 0x08)
- call->chanflags = FLAG_EXCLUSIVE;
- else
call->chanflags = FLAG_PREFERRED;
+ }
+
+ need_extended_channel_octets = 0;
+ if (ie->data[0] & 0x20) {
+ /* PRI encoded interface type */
+ switch (ie->data[0] & 0x03) {
+ case 0x00:
+ /* No channel */
+ call->channelno = 0;
+ call->chanflags = FLAG_PREFERRED;
+ break;
+ case 0x01:
+ /* As indicated in following octets */
+ need_extended_channel_octets = 1;
+ break;
+ case 0x03:
+ /* Any channel */
+ call->chanflags = FLAG_PREFERRED;
+ break;
+ default:
+ pri_error(ctrl, "!! Unexpected Channel selection %d\n", ie->data[0] & 0x03);
+ return -1;
+ }
+ } else {
+ /* BRI encoded interface type */
+ switch (ie->data[0] & 0x03) {
+ case 0x00:
+ /* No channel */
+ call->channelno = 0;
+ call->chanflags = FLAG_PREFERRED;
+ break;
+ case 0x03:
+ /* Any channel */
+ call->chanflags = FLAG_PREFERRED;
+ break;
+ default:
+ /* Specified B channel (B1 or B2) */
+ call->channelno = ie->data[0] & 0x03;
+ break;
+ }
+ }
+
pos++;
if (ie->data[0] & 0x40) {
/* DS1 specified -- stop here */
call->ds1no = ie->data[1] & 0x7f;
call->ds1explicit = 1;
pos++;
- } else
+ } else {
call->ds1explicit = 0;
-
- if (pos+2 < len) {
+ }
+
+ if (ie->data[0] & 0x04) {
+ /* D channel call. Signaling only. */
+ call->cis_call = 1;
+ call->chanflags = FLAG_EXCLUSIVE;/* For safety mark this channel as exclusive. */
+ call->channelno = 0;
+ return 0;
+ }
+
+ if (need_extended_channel_octets && pos + 2 < len) {
/* More coming */
if ((ie->data[pos] & 0x0f) != 3) {
+ /* Channel type/mapping is not for B channel units. */
pri_error(ctrl, "!! Unexpected Channel Type %d\n", ie->data[1] & 0x0f);
return -1;
}
@@ -697,25 +741,21 @@
call->slotmap <<= 8;
call->slotmap |= ie->data[x + pos];
}
- return 0;
} else {
pos++;
/* Only expect a particular channel */
call->channelno = ie->data[pos] & 0x7f;
if (ctrl->chan_mapping_logical && call->channelno > 15)
call->channelno++;
- return 0;
- }
- } else
- return 0;
- return -1;
+ }
+ }
+ return 0;
}
static int transmit_channel_id(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order)
{
- int pos=0;
-
-
+ int pos = 0;
+
/* We are ready to transmit single IE only */
if (order > 1)
return 0;
@@ -729,61 +769,69 @@
ie->data[pos++] = ctrl->bri ? 0x8c : 0xac;
return pos + 2;
}
-
+
/* Start with standard stuff */
if (ctrl->switchtype == PRI_SWITCH_GR303_TMC)
ie->data[pos] = 0x69;
else if (ctrl->bri) {
ie->data[pos] = 0x80;
- if (call->channelno > -1)
- ie->data[pos] |= (call->channelno & 0x3);
- } else
- ie->data[pos] = 0xa1;
- /* Add exclusive flag if necessary */
- if (call->chanflags & FLAG_EXCLUSIVE)
+ ie->data[pos] |= (call->channelno & 0x3);
+ } else {
+ /* PRI */
+ if (call->slotmap != -1 || (call->chanflags & FLAG_WHOLE_INTERFACE)) {
+ /* Specified channel */
+ ie->data[pos] = 0xa1;
+ } else if (call->channelno < 0 || call->channelno == 0xff) {
+ /* Any channel */
+ ie->data[pos] = 0xa3;
+ } else if (!call->channelno) {
+ /* No channel */
+ ie->data[pos] = 0xa0;
+ } else {
+ /* Specified channel */
+ ie->data[pos] = 0xa1;
+ }
+ }
+ if (call->chanflags & FLAG_EXCLUSIVE) {
+ /* Channel is exclusive */
ie->data[pos] |= 0x08;
- else if (!(call->chanflags & FLAG_PREFERRED)) {
+ } else if (!call->chanflags) {
/* Don't need this IE */
return 0;
}
if (((ctrl->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit) {
- /* Note that we are specifying the identifier */
+ /* We are specifying the interface. Octet 3.1 */
ie->data[pos++] |= 0x40;
- /* We need to use the Channel Identifier Present thingy. Just specify it and we're done */
ie->data[pos++] = 0x80 | call->ds1no;
- } else
- pos++;
-
- if (ctrl->bri)
- return pos + 2;
-
- if ((call->channelno > -1) || (call->slotmap != -1)) {
- /* We'll have the octet 8.2 and 8.3's present */
- ie->data[pos++] = 0x83;
- if (call->channelno > -1) {
+ } else {
+ ++pos;
+ }
+
+ if (!ctrl->bri && (ie->data[0] & 0x03) == 0x01 /* Specified channel */
+ && !(call->chanflags & FLAG_WHOLE_INTERFACE)) {
+ /* The 3.2 and 3.3 octets need to be present */
+ ie->data[pos] = 0x83;
+ if (call->slotmap != -1) {
+ int octet;
+
+ /* We have to send a channel map */
+ ie->data[pos++] |= 0x10;
+ for (octet = 3; octet--;) {
+ ie->data[pos++] = (call->slotmap >> (8 * octet)) & 0xff;
+ }
+ } else {
/* Channel number specified */
- if (ctrl->chan_mapping_logical && call->channelno > 16)
+ ++pos;
+ if (ctrl->chan_mapping_logical && call->channelno > 16) {
ie->data[pos++] = 0x80 | (call->channelno - 1);
- else
+ } else {
ie->data[pos++] = 0x80 | call->channelno;
- return pos + 2;
- }
- /* We have to send a channel map */
- if (call->slotmap != -1) {
- ie->data[pos-1] |= 0x10;
- ie->data[pos++] = (call->slotmap & 0xff0000) >> 16;
- ie->data[pos++] = (call->slotmap & 0xff00) >> 8;
- ie->data[pos++] = (call->slotmap & 0xff);
- return pos + 2;
- }
- }
- if (call->ds1no > 0) {
- /* We're done */
- return pos + 2;
- }
- pri_error(ctrl, "!! No channel map, no channel, and no ds1? What am I supposed to identify?\n");
- return -1;
+ }
+ }
+ }
+
+ return pos + 2;
}
static void dump_channel_id(int full_ie, struct pri *ctrl, q931_ie *ie, int len, char prefix)
@@ -3359,11 +3407,14 @@
return -1;
}
if (channel > -1) {
- channel &= 0xff;
+ c->channelno = channel & 0xff;
+ c->chanflags = FLAG_EXCLUSIVE;
+ } else {
+ c->channelno = channel;
+ c->chanflags = FLAG_EXCLUSIVE | FLAG_WHOLE_INTERFACE;
}
c->ds1no = span;
- c->channelno = channel;
- c->chanflags |= FLAG_EXCLUSIVE;
+ c->ds1explicit = 0;
c->changestatus = changestatus;
return send_message(ctrl, c, (MAINTENANCE_PROTOCOL_DISCRIMINATOR_1 << 8) | NATIONAL_SERVICE, maintenance_service_ies);
}
@@ -3659,7 +3710,7 @@
ctrl->schedev = 1;
ctrl->ev.e = PRI_EVENT_HANGUP_ACK;
ctrl->ev.hangup.subcmds = &ctrl->subcmds;
- ctrl->ev.hangup.channel = c->channelno;
+ ctrl->ev.hangup.channel = q931_encode_channel(c);
ctrl->ev.hangup.cause = c->cause;
ctrl->ev.hangup.cref = c->cr;
ctrl->ev.hangup.call = c;
@@ -3825,23 +3876,24 @@
c->userl3 = -1;
c->ds1no = (req->channel & 0xff00) >> 8;
c->ds1explicit = (req->channel & 0x10000) >> 16;
- req->channel &= 0xff;
if ((ctrl->localtype == PRI_CPE) && ctrl->subchannel && !ctrl->bri) {
- req->channel = 0;
- req->exclusive = 0;
- }
-
- c->channelno = req->channel;
+ c->channelno = 0;
+ c->chanflags = 0;
+ } else {
+ c->channelno = req->channel & 0xff;
+ if (req->exclusive) {
+ c->chanflags = FLAG_EXCLUSIVE;
+ } else {
+ c->chanflags = FLAG_PREFERRED;
+ }
+ }
+
c->slotmap = -1;
c->nonisdn = req->nonisdn;
c->newcall = 0;
c->cis_call = req->cis_call;
c->cis_auto_disconnect = req->cis_auto_disconnect;
c->complete = req->numcomplete;
- if (req->exclusive)
- c->chanflags = FLAG_EXCLUSIVE;
- else if (c->channelno)
- c->chanflags = FLAG_PREFERRED;
if (req->caller.number.valid) {
c->local_id = req->caller;
@@ -4085,7 +4137,9 @@
c->channelno = -1;
c->slotmap = -1;
c->chanflags = 0;
+ c->ds1explicit = 0;
c->ds1no = 0;
+ c->cis_call = 0;
c->ri = -1;
c->changestatus = -1;
break;
@@ -4111,6 +4165,8 @@
c->slotmap = -1;
c->chanflags = 0;
c->ds1no = 0;
+ c->ds1explicit = 0;
+ c->cis_call = 0;
c->ri = -1;
break;
case Q931_FACILITY:
@@ -4184,6 +4240,9 @@
break;
case Q931_RESTART_ACKNOWLEDGE:
c->channelno = -1;
+ c->ds1no = 0;
+ c->ds1explicit = 0;
+ c->cis_call = 0;
break;
case Q931_INFORMATION:
/*
@@ -4381,7 +4440,7 @@
case NATIONAL_SERVICE:
if (c->channelno > 0) {
ctrl->ev.e = PRI_EVENT_SERVICE;
- ctrl->ev.service.channel = c->channelno | (c->ds1no << 8);
+ ctrl->ev.service.channel = q931_encode_channel(c);
ctrl->ev.service.changestatus = 0x0f & c->changestatus;
} else {
switch (0x0f & c->changestatus) {
@@ -4403,7 +4462,7 @@
case NATIONAL_SERVICE_ACKNOWLEDGE:
if (c->channelno > 0) {
ctrl->ev.e = PRI_EVENT_SERVICE_ACK;
- ctrl->ev.service_ack.channel = c->channelno | (c->ds1no << 8);
+ ctrl->ev.service_ack.channel = q931_encode_channel(c);
ctrl->ev.service_ack.changestatus = 0x0f & c->changestatus;
} else {
switch (0x0f & c->changestatus) {
@@ -4440,8 +4499,7 @@
{
ctrl->ev.e = PRI_EVENT_FACILITY;
ctrl->ev.facility.subcmds = &ctrl->subcmds;
- ctrl->ev.facility.channel =
- call->channelno | (call->ds1no << 8) | (call->ds1explicit << 16);
+ ctrl->ev.facility.channel = q931_encode_channel(call);
ctrl->ev.facility.cref = call->cr;
ctrl->ev.facility.call = call;
@@ -4486,7 +4544,7 @@
restart_ack(ctrl, c);
/* Notify user of restart event */
ctrl->ev.e = PRI_EVENT_RESTART;
- ctrl->ev.restart.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+ ctrl->ev.restart.channel = q931_encode_channel(c);
return Q931_RES_HAVEEVENT;
case Q931_SETUP:
if (missingmand) {
@@ -4536,7 +4594,7 @@
ctrl->ev.e = PRI_EVENT_RING;
ctrl->ev.ring.subcmds = &ctrl->subcmds;
- ctrl->ev.ring.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+ ctrl->ev.ring.channel = q931_encode_channel(c);
/* Calling party information */
ctrl->ev.ring.callingpres = q931_party_id_presentation(&c->remote_id);
@@ -4611,7 +4669,7 @@
c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
ctrl->ev.e = PRI_EVENT_RINGING;
ctrl->ev.ringing.subcmds = &ctrl->subcmds;
- ctrl->ev.ringing.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+ ctrl->ev.ringing.channel = q931_encode_channel(c);
ctrl->ev.ringing.cref = c->cr;
ctrl->ev.ringing.call = c;
ctrl->ev.ringing.progress = c->progress;
@@ -4644,7 +4702,7 @@
ctrl->ev.e = PRI_EVENT_ANSWER;
ctrl->ev.answer.subcmds = &ctrl->subcmds;
- ctrl->ev.answer.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+ ctrl->ev.answer.channel = q931_encode_channel(c);
ctrl->ev.answer.cref = c->cr;
ctrl->ev.answer.call = c;
ctrl->ev.answer.progress = c->progress;
@@ -4714,7 +4772,7 @@
q931_status(ctrl,c,PRI_CAUSE_WRONG_MESSAGE);
break;
}
- ctrl->ev.proceeding.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+ ctrl->ev.proceeding.channel = q931_encode_channel(c);
if (mh->msg == Q931_CALL_PROCEEDING) {
ctrl->ev.e = PRI_EVENT_PROCEEDING;
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING);
@@ -4775,7 +4833,7 @@
if (!c->sugcallstate) {
#endif
ctrl->ev.hangup.subcmds = &ctrl->subcmds;
- ctrl->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+ ctrl->ev.hangup.channel = q931_encode_channel(c);
ctrl->ev.hangup.cause = c->cause;
ctrl->ev.hangup.cref = c->cr;
ctrl->ev.hangup.call = c;
@@ -4804,7 +4862,7 @@
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
c->peercallstate = Q931_CALL_STATE_NULL;
ctrl->ev.hangup.subcmds = &ctrl->subcmds;
- ctrl->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+ ctrl->ev.hangup.channel = q931_encode_channel(c);
ctrl->ev.hangup.cause = c->cause;
ctrl->ev.hangup.cref = c->cr;
ctrl->ev.hangup.call = c;
@@ -4840,7 +4898,7 @@
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
ctrl->ev.e = PRI_EVENT_HANGUP;
ctrl->ev.hangup.subcmds = &ctrl->subcmds;
- ctrl->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+ ctrl->ev.hangup.channel = q931_encode_channel(c);
ctrl->ev.hangup.cause = c->cause;
ctrl->ev.hangup.cref = c->cr;
ctrl->ev.hangup.call = c;
@@ -4875,7 +4933,7 @@
/* Return such an event */
ctrl->ev.e = PRI_EVENT_HANGUP_REQ;
ctrl->ev.hangup.subcmds = &ctrl->subcmds;
- ctrl->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+ ctrl->ev.hangup.channel = q931_encode_channel(c);
ctrl->ev.hangup.cause = c->cause;
ctrl->ev.hangup.cref = c->cr;
ctrl->ev.hangup.call = c;
@@ -4891,7 +4949,7 @@
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
c->peercallstate = Q931_CALL_STATE_NULL;
ctrl->ev.e = PRI_EVENT_RESTART_ACK;
- ctrl->ev.restartack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+ ctrl->ev.restartack.channel = q931_encode_channel(c);
return Q931_RES_HAVEEVENT;
case Q931_INFORMATION:
/* XXX We're handling only INFORMATION messages that contain
@@ -4906,14 +4964,14 @@
ctrl->ev.e = PRI_EVENT_KEYPAD_DIGIT;
ctrl->ev.digit.subcmds = &ctrl->subcmds;
ctrl->ev.digit.call = c;
- ctrl->ev.digit.channel = c->channelno | (c->ds1no << 8);
+ ctrl->ev.digit.channel = q931_encode_channel(c);
libpri_copy_string(ctrl->ev.digit.digits, c->keypad_digits, sizeof(ctrl->ev.digit.digits));
return Q931_RES_HAVEEVENT;
}
ctrl->ev.e = PRI_EVENT_INFO_RECEIVED;
ctrl->ev.ring.subcmds = &ctrl->subcmds;
ctrl->ev.ring.call = c;
- ctrl->ev.ring.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+ ctrl->ev.ring.channel = q931_encode_channel(c);
libpri_copy_string(ctrl->ev.ring.callednum, c->overlap_digits, sizeof(ctrl->ev.ring.callednum));
libpri_copy_string(ctrl->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(ctrl->ev.ring.callingsubaddr));
ctrl->ev.ring.complete = c->complete; /* this covers IE 33 (Sending Complete) */
@@ -4933,7 +4991,7 @@
c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
ctrl->ev.e = PRI_EVENT_SETUP_ACK;
ctrl->ev.setup_ack.subcmds = &ctrl->subcmds;
- ctrl->ev.setup_ack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+ ctrl->ev.setup_ack.channel = q931_encode_channel(c);
ctrl->ev.setup_ack.call = c;
cur = c->apdus;
@@ -5004,7 +5062,7 @@
default:
ctrl->ev.e = PRI_EVENT_NOTIFY;
ctrl->ev.notify.subcmds = &ctrl->subcmds;
- ctrl->ev.notify.channel = c->channelno;
+ ctrl->ev.notify.channel = q931_encode_channel(c);
ctrl->ev.notify.info = c->notify;
res = Q931_RES_HAVEEVENT;
break;
@@ -5057,7 +5115,7 @@
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
c->peercallstate = Q931_CALL_STATE_NULL;
ctrl->ev.hangup.subcmds = &ctrl->subcmds;
- ctrl->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
+ ctrl->ev.hangup.channel = q931_encode_channel(c);
ctrl->ev.hangup.cause = c->cause;
ctrl->ev.hangup.cref = c->cr;
ctrl->ev.hangup.call = c;
More information about the libpri-commits
mailing list