Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* JBoss, Home of Professional Open Source
* Copyright 2011, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.restcomm.protocols.ss7.mtp;
/**
*
*
* @author kulikov
*/
public class FastHDLC {
public static final int RETURN_COMPLETE_FLAG = 0x1000;
public static final int RETURN_DISCARD_FLAG = 0x2000;
public static final int RETURN_EMPTY_FLAG = 0x4000;
/*
* Unlike most HDLC implementations, we define only two states, when we are in a valid frame, and when we are searching for
* a frame header
*/
public static final int FRAME_SEARCH = 0;
public static final int PROCESS_FRAME = 1;
/*
*
* HDLC Search State table -- Look for a frame header. The return value of this table is as follows:
*
* |---8---|---7---|---6---|---5---|---4---|---3---|---2---|---1---| | Z E R O E S | Next | Bits Consumed |
* |-------|-------|-------|-------|-------|-------|-------|-------|
*
* The indexes for this table are the state (0 or 1) and the next 8 bits of the stream.
*
* Note that this table is only used for state 0 and 1.
*
* The user should discard the top "bits consumed" bits of data before the next call. "Next state" represents the actual
* next state for decoding.
*/
private int[] hdlc_search = new int[256];
/*
* HDLC Data Table
*
* The indexes to this table are the number of one's we've seen so far (0-5) and the next 10 bits of input (which is enough
* to guarantee us that we will retrieve at least one byte of data (or frame or whatever).
*
* The format for the return value is:
*
* Bits 15: Status (1=Valid Data, 0=Control Frame (see bits 7-0 for type)) Bits 14-12: Number of ones in a row, so far Bits
* 11-8: The number of bits consumed (0-10) Bits 7-0: The return data (if appropriate)
*
* The next state is simply bit #15
*/
public static final int CONTROL_COMPLETE = 1;
public static final int CONTROL_ABORT = 2;
public static final int STATUS_MASK = (1 << 15);
public static final int STATUS_VALID = (1 << 15);
public static final int STATUS_CONTROL = (0 << 15);
public static final int STATE_MASK = (1 << 15);
public static final int ONES_MASK = (7 << 12);
public static final int DATA_MASK = (0xff);
private int[][] hdlc_frame = new int[6][1024];
private int[] minbits = new int[] { 8, 10 };
/*
* Last, but not least, we have the encoder table. It takes as its indices the number of ones so far and a byte of data and
* returns an int composed of the following fields:
*
* Bots 31-22: Actual Data Bits 21-16: Unused Bits 15-8: Number of ones Bits 3-0: Number of bits of output (13-4) to use
*
* Of course we could optimize by reducing to two tables, but I don't really think it's worth the trouble at this point.
*/
private int[][] hdlc_encode = new int[6][256];
private int hdlc_search_precalc(int c) {
int x, p = 0;
/*
* Look for a flag. If this isn't a flag, line us up for the next possible shot at a flag
*/
/*
* If it's a flag, we go to state 1, and have consumed 8 bits
*/
if (c == 0x7e) {
return 0x10 | 8;
/*
* If it's an abort, we stay in the same state and have consumed 8 bits
*/
}
if (c == 0x7f) {
return 0x00 | 8;
/*
* If it's all 1's, we state in the same state and have consumed 8 bits
*/
}
if (c == 0xff) {
return 0x00 | 8;
/*
* If we get here, we must have at least one zero in us but we're not the flag. So, start at the end (LSB) and work
* our way to the top (MSB) looking for a zero. The position of that 0 is most optimistic start of a real frame
* header
*/
}
x = 1;
p = 7;
while ((p != 0) && ((c & x) != 0)) {
x <<= 1;
p--;
}
return p;
}
private int HFP(int status, int ones, int bits, int data) {
return ((status) | ((ones) << 12) | ((bits) << 8) | (data));
}
private int hdlc_frame_precalc(int x, int c) {
/*
* Assume we have seen 'x' one's so far, and have read the bottom 10 bytes of c (MSB first). Now, we HAVE to have a byte
* of data or a frame or something. We are assumed to be at the beginning of a byte of data or something
*/
int ones = x;
int data = 0;
int bits = 0;
int consumed = 0;
while (bits < 8) {
data >>>= 1;
consumed++;
if (ones == 5) {
/* We've seen five ones */
if ((c & 0x0200) != 0) {
/* Another one -- Some sort of signal frame */
if ((!((c & 0x0100) != 0)) && (bits == 6)) {
/* This is a frame terminator (10) */
return HFP(0, 0, 8, CONTROL_COMPLETE);
} else {
/*
* Yuck! It's something else... Abort this entire frame, and start looking for a good frame
*/
return HFP(0, 0, consumed + 1, CONTROL_ABORT);
}
} else {
/* It's an inserted zero, just skip it */
ones = 0;
data <<= 1;
}
} else {
/*
* Add it to our bit list, LSB to MSB
*/
if ((c & 0x0200) != 0) {
data |= 0x80;
ones++;
} else {
ones = 0;
}
bits++;
}
c <<= 1;
}
/* Consume the extra 0 now rather than later. */
if (ones == 5) {
ones = 0;
consumed++;
}
return HFP(STATUS_VALID, ones, consumed, data);
}
private int hdlc_encode_precalc(int x, int y) {
int bits = 0;
int ones = x;
int data = 0;
int z;
for (z = 0; z < 8; z++) {
/* Zero-stuff if needed */
if (ones == 5) {
/* Stuff a zero */
data <<= 1;
ones = 0;
bits++;
}
if ((y & 0x01) != 0) {
/* There's a one */
data <<= 1;
data |= 0x1;
ones++;
bits++;
} else {
data <<= 1;
ones = 0;
bits++;
}
y >>= 1;
}
/* Special case -- Stuff the zero at the end if appropriate */
if (ones == 5) {
/* Stuff a zero */
data <<= 1;
ones = 0;
bits++;
}
data <<= (10 - bits);
return (data << 22) | (ones << 8) | (bits);
}
public void fasthdlc_precalc() {
int x;
int y;
/* First the easy part -- the searching */
for (x = 0; x < 256; x++) {
hdlc_search[x] = hdlc_search_precalc(x);
}
/* Now the hard part -- the frame tables */
for (x = 0; x < 6; x++) {
/*
* Given the # of preceeding ones, process the next byte of input (up to 10 actual bits)
*/
for (y = 0; y < 1024; y++) {
hdlc_frame[x][y] = hdlc_frame_precalc(x, y);
}
}
/* Now another not-so-hard part, the encoding table */
for (x = 0; x < 6; x++) {
for (y = 0; y < 256; y++) {
hdlc_encode[x][y] = hdlc_encode_precalc(x, y);
}
}
}
public void fasthdlc_init(HdlcState h) {
/* Initializes all states appropriately */
h.state = 0;
h.bits = 0;
h.data = 0;
h.ones = 0;
}
public int fasthdlc_tx_load_nocheck(HdlcState h, int c) {
int res;
res = hdlc_encode[h.ones][c];
h.ones = ((res & 0xf00) >> 8);
h.data |= ((res & 0xffc00000) >>> h.bits);
h.bits += (res & 0xf);
return 0;
}
public int fasthdlc_tx_load(HdlcState h, int c) {
/* Gotta have at least 10 bits left */
if (h.bits > 22) {
return -1;
}
return fasthdlc_tx_load_nocheck(h, c);
}
public int fasthdlc_tx_frame_nocheck(HdlcState h) {
h.ones = 0;
h.data |= (0x7e000000 >> h.bits);
h.bits += 8;
return 0;
}
public int fasthdlc_tx_frame(HdlcState h) {
if (h.bits > 24) {
return -1;
}
return fasthdlc_tx_frame_nocheck(h);
}
public int fasthdlc_tx_run_nocheck(HdlcState h) {
int b;
b = h.data >> 24;
h.bits -= 8;
h.data <<= 8;
return b;
}
public int fasthdlc_tx_run(HdlcState h) {
if (h.bits < 8) {
return -1;
}
return fasthdlc_tx_run_nocheck(h);
}
public int fasthdlc_rx_load_nocheck(HdlcState h, int b) {
/* Put the new byte in the data stream */
h.data |= b << (24 - h.bits);
h.bits += 8;
return 0;
}
public int fasthdlc_rx_load(HdlcState h, int b) {
/* Make sure we have enough space */
if (h.bits > 24) {
return -1;
}
return fasthdlc_rx_load_nocheck(h, b);
}
/*
* Returns a data character if available, logical OR'd with zero or more of RETURN_COMPLETE_FLAG, RETURN_DISCARD_FLAG, and
* RETURN_EMPTY_FLAG, signifying a complete frame, a discarded frame, or there is nothing to return.
*/
public int fasthdlc_rx_run(HdlcState h) {
int next;
int retval = RETURN_EMPTY_FLAG;
while ((h.bits >= minbits[h.state]) && (retval == RETURN_EMPTY_FLAG)) {
/*
* Run until we can no longer be assured that we will have enough bits to continue
*/
switch (h.state) {
case FRAME_SEARCH:
/*
* Look for an HDLC frame, keying from the top byte.
*/
next = hdlc_search[(h.data >> 24) & 0xff];
h.bits -= next & 0x0f;
h.data <<= next & 0x0f;
h.state = (next >> 4) & 0xff;
h.ones = 0;
break;
case PROCESS_FRAME:
/* Process as much as the next ten bits */
next = hdlc_frame[h.ones][(h.data >>> 22) & 0x3ff]; // Must be 10 bits here, not 8, that's all
// next = hdlc_frame_precalc(h.ones, (h.data >> 22)& 0x3ff);
h.bits -= (((next & 0x0f00) >> 8) & 0xff);
h.data <<= (((next & 0x0f00) >> 8) & 0xff);
h.state = ((next & STATE_MASK) >> 15) & 0xff;
h.ones = (((next & ONES_MASK) >> 12) & 0xff);
switch (next & STATUS_MASK) {
case STATUS_CONTROL:
if ((next & CONTROL_COMPLETE) != 0) {
/* A complete, valid frame received */
retval = (RETURN_COMPLETE_FLAG);
/* Stay in this state */
h.state = 1;
} else {
/* An abort (either out of sync of explicit) */
retval = (RETURN_DISCARD_FLAG);
}
break;
case STATUS_VALID:
retval = (next & DATA_MASK);
}
}
}
return retval;
}
}