[libpri-commits] rmudgett: branch 1.4 r2277 - in /branches/1.4: pri_internal.h q931.c
SVN commits to the libpri project
libpri-commits at lists.digium.com
Fri Dec 16 13:26:58 CST 2011
Author: rmudgett
Date: Fri Dec 16 13:26:56 2011
New Revision: 2277
URL: http://svnview.digium.com/svn/libpri?view=rev&rev=2277
Log:
Implement handling a multi-channel RESTART request.
The channel id ie can supply a slotmap or list of channels. For a RESTART
message, this can be handy to indicate multiple channels that need to be
restarted at the same time.
An incoming RESTART request will now generate a PRI_EVENT_RESTART to the
upper layer for each channel indicated in the request. If the event is
successfully generated for all indicated channels then a
RESTART_ACKNOWLEDGE is sent back to the peer indicating all channels
restarted.
* Add the ability to process a channel id ie channel list with a RESTART
request.
* Add the ability to process slotmaps with a RESTART request.
(closes issue PRI-93)
Reported by: Marcin Kowalczyk
Patches:
jira_pri_93.patch (license #5621) patch uploaded by rmudgett
Tested by: zvision, rmudgett
(closes issue PRI-71)
Reported by: Torrey Searle
Tested by: rmudgett
Modified:
branches/1.4/pri_internal.h
branches/1.4/q931.c
Modified: branches/1.4/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_internal.h?view=diff&rev=2277&r1=2276&r2=2277
==============================================================================
--- branches/1.4/pri_internal.h (original)
+++ branches/1.4/pri_internal.h Fri Dec 16 13:26:56 2011
@@ -647,6 +647,19 @@
/* AOC charge requesting on Setup */
int aoc_charging_request;
+
+ unsigned int slotmap_size:1;/* TRUE if the slotmap is E1 (32 bits). */
+
+ struct {
+ /*! Timer ID of RESTART notification events to upper layer. */
+ int timer;
+ /*! Current RESTART notification index. */
+ int idx;
+ /*! Number of channels in the channel ID list. */
+ int count;
+ /*! Channel ID list */
+ char chan_no[32];
+ } restart;
};
enum CC_STATES {
Modified: branches/1.4/q931.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/q931.c?view=diff&rev=2277&r1=2276&r2=2277
==============================================================================
--- branches/1.4/q931.c (original)
+++ branches/1.4/q931.c Fri Dec 16 13:26:56 2011
@@ -1156,6 +1156,8 @@
int pos = 0;
int need_extended_channel_octets;/*!< TRUE if octets 3.2 and 3.3 need to be present. */
+ call->restart.count = 0;
+
if (ie->data[0] & 0x08) {
call->chanflags = FLAG_EXCLUSIVE;
} else {
@@ -1224,32 +1226,62 @@
/* 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);
+ pri_error(ctrl, "!! Unexpected Channel Type %d\n", ie->data[pos] & 0x0f);
return -1;
}
if ((ie->data[pos] & 0x60) != 0) {
- pri_error(ctrl, "!! Invalid CCITT coding %d\n", (ie->data[1] & 0x60) >> 5);
+ pri_error(ctrl, "!! Invalid CCITT coding %d\n", (ie->data[pos] & 0x60) >> 5);
return -1;
}
if (ie->data[pos] & 0x10) {
- /*
- * Expect Slot Map
- * Note that we are assuming only T1's use slot maps which is wrong
- * but oh well... We would need to know what type of line we are
- * connected with (T1 or E1) to interpret the map correctly anyway.
- */
+ /* Expect Slot Map */
call->slotmap = 0;
pos++;
- for (x=0;x<3;x++) {
+ call->slotmap_size = (ie->len - pos > 3) ? 1 : 0;
+ for (x = 0; x < (call->slotmap_size ? 4 : 3); ++x) {
call->slotmap <<= 8;
call->slotmap |= ie->data[x + pos];
+ }
+
+ if (msgtype == Q931_RESTART) {
+ int bit;
+
+ /* Convert the slotmap to a channel list for RESTART support. */
+ for (bit = 0; bit < ARRAY_LEN(call->restart.chan_no); ++bit) {
+ if (call->slotmap & (1UL << bit)) {
+ call->restart.chan_no[call->restart.count++] = bit
+ + (call->slotmap_size ? 0 : 1);
+ }
+ }
}
} else {
pos++;
/* Only expect a particular channel */
call->channelno = ie->data[pos] & 0x7f;
- if (ctrl->chan_mapping_logical && call->channelno > 15)
+ if (ctrl->chan_mapping_logical && call->channelno > 15) {
call->channelno++;
+ }
+
+ if (msgtype == Q931_RESTART) {
+ /* Read in channel list for RESTART support. */
+ while (call->restart.count < ARRAY_LEN(call->restart.chan_no)) {
+ int chan_no;
+
+ chan_no = ie->data[pos] & 0x7f;
+ if (ctrl->chan_mapping_logical && chan_no > 15) {
+ ++chan_no;
+ }
+ call->restart.chan_no[call->restart.count++] = chan_no;
+ if (ie->data[pos++] & 0x80) {
+ /* Channel list finished. */
+ break;
+ }
+ if (ie->len <= pos) {
+ /* No more ie contents. */
+ break;
+ }
+ }
+ }
}
}
return 0;
@@ -1322,17 +1354,35 @@
if (0 < call->channelno && call->channelno != 0xff) {
/* Channel number specified and preferred over slot map if we have one. */
++pos;
- if (ctrl->chan_mapping_logical && call->channelno > 16) {
- ie->data[pos++] = 0x80 | (call->channelno - 1);
+ if (msgtype == Q931_RESTART_ACKNOWLEDGE && call->restart.count) {
+ int chan_no;
+ int idx;
+
+ /* Build RESTART_ACKNOWLEDGE channel list */
+ for (idx = 0; idx < call->restart.count; ++idx) {
+ chan_no = call->restart.chan_no[idx];
+ if (ctrl->chan_mapping_logical && chan_no > 16) {
+ --chan_no;
+ }
+ if (call->restart.count <= idx + 1) {
+ /* Last channel list channel. */
+ chan_no |= 0x80;
+ }
+ ie->data[pos++] = chan_no;
+ }
} else {
- ie->data[pos++] = 0x80 | call->channelno;
+ if (ctrl->chan_mapping_logical && call->channelno > 16) {
+ ie->data[pos++] = 0x80 | (call->channelno - 1);
+ } else {
+ ie->data[pos++] = 0x80 | call->channelno;
+ }
}
} else if (call->slotmap != -1) {
int octet;
/* We have to send a slot map */
ie->data[pos++] |= 0x10;
- for (octet = 3; octet--;) {
+ for (octet = call->slotmap_size ? 4 : 3; octet--;) {
ie->data[pos++] = (call->slotmap >> (8 * octet)) & 0xff;
}
} else {
@@ -4240,6 +4290,7 @@
struct pri *ctrl;
ctrl = cur->pri;
+ pri_schedule_del(ctrl, cur->restart.timer);
pri_schedule_del(ctrl, cur->retranstimer);
pri_schedule_del(ctrl, cur->hold_timer);
pri_schedule_del(ctrl, cur->fake_clearing_timer);
@@ -8194,6 +8245,60 @@
/*!
* \internal
+ * \brief Restart channel notify event for upper layer notify chain timeout.
+ *
+ * \param data Callback data pointer.
+ *
+ * \return Nothing
+ */
+static void q931_restart_notify_timeout(void *data)
+{
+ struct q931_call *call = data;
+ struct pri *ctrl = call->pri;
+
+ /* Create channel restart event to upper layer. */
+ call->channelno = call->restart.chan_no[call->restart.idx++];
+ ctrl->ev.e = PRI_EVENT_RESTART;
+ ctrl->ev.restart.channel = q931_encode_channel(call);
+ ctrl->schedev = 1;
+
+ /* Reschedule for next channel restart event needed. */
+ if (call->restart.idx < call->restart.count) {
+ call->restart.timer = pri_schedule_event(ctrl, 0, q931_restart_notify_timeout,
+ call);
+ } else {
+ /* No more restart events needed. */
+ call->restart.timer = 0;
+
+ /* Send back the Restart Acknowledge. All channels are now restarted. */
+ if (call->slotmap != -1) {
+ /* Send slotmap format. */
+ call->channelno = -1;
+ }
+ restart_ack(ctrl, call);
+ }
+}
+
+/*!
+ * \internal
+ * \brief Setup restart channel notify events for upper layer.
+ *
+ * \param call Q.931 call leg.
+ *
+ * \return Nothing
+ */
+static void q931_restart_notify(struct q931_call *call)
+{
+ struct pri *ctrl = call->pri;
+
+ /* Start notify chain. */
+ pri_schedule_del(ctrl, call->restart.timer);
+ call->restart.idx = 0;
+ q931_restart_notify_timeout(call);
+}
+
+/*!
+ * \internal
* \brief Process the decoded information in the Q.931 message.
*
* \param ctrl D channel controller.
@@ -8227,11 +8332,24 @@
}
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_RESTART);
c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST;
- /* Send back the Restart Acknowledge */
- restart_ack(ctrl, c);
- /* Notify user of restart event */
- ctrl->ev.e = PRI_EVENT_RESTART;
- ctrl->ev.restart.channel = q931_encode_channel(c);
+
+ /* Notify upper layer of restart event */
+ if ((c->channelno == -1 && c->slotmap == -1) || !c->restart.count) {
+ /*
+ * Whole link restart or channel not identified by Channel ID ie
+ * 3.3 octets.
+ *
+ * Send back the Restart Acknowledge
+ */
+ restart_ack(ctrl, c);
+
+ /* Create channel restart event to upper layer. */
+ ctrl->ev.e = PRI_EVENT_RESTART;
+ ctrl->ev.restart.channel = q931_encode_channel(c);
+ } else {
+ /* Start notify chain. */
+ q931_restart_notify(c);
+ }
return Q931_RES_HAVEEVENT;
case Q931_REGISTER:
q931_display_subcmd(ctrl, c);
More information about the libpri-commits
mailing list