berencoder.java
来自「opennms得相关源码 请大家看看」· Java 代码 · 共 1,296 行 · 第 1/3 页
JAVA
1,296 行
//// This file is part of the OpenNMS(R) Application.//// OpenNMS(R) is Copyright (C) 2002-2003 The OpenNMS Group, Inc. All rights reserved.// OpenNMS(R) is a derivative work, containing both original code, included code and modified// code that was published under the GNU General Public License. Copyrights for modified // and included code are below.//// OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.//// Copyright (C) 1999-2001 Oculan Corp. All rights reserved.//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program 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 General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//// For more information contact:// OpenNMS Licensing <license@opennms.org>// http://www.opennms.org/// http://www.opennms.com///// Tab Size = 8//// BerEncoder.java,v 1.1.1.1 2001/11/11 17:27:23 ben Exp//package org.opennms.protocols.snmp.asn1;import java.math.BigInteger;/** * The BerEncoder class is used to implement the AsnEncoder interface for the * Basic Encoding Rules (BER). The encoding rules are used to encode and decode * SNMP values using BER. * * @author <a href="http://www.opennms.org">OpenNMS </a> * @author <a href="mailto:weave@oculan.com">Brian Weaver </a> * @version 1.1.1.1 */public class BerEncoder implements AsnEncoder { /** * Defines the ASN.1 long length marker for the Basic Encoding Rule (BER) */ private static final byte LONG_LENGTH = (byte) 0x80; /** * Defines the "high bit" that is the sign extension bit for a 8-bit signed * value. */ private static final byte HIGH_BIT = (byte) 0x80; /** * Defines the BER extension "value" that is used to mark an extension type. */ private static final byte EXTENSION_ID = (byte) 0x1F; /** * Defines the BER constructor id */ private static final byte CONSTRUCTOR = (byte) 0x20; /** * Converts a primitive byte to a primitive long using "unsigned" logic. * * @param b * The 8-bit value to convert * @return Returns the 32-bit converted value * */ protected static int byteToInt(byte b) { return (b < 0) ? 256 + (int) b : (int) b; } /** * Converts a primitive byte to a primitive long. The byte is converted * using "unsigned" logic * * @param b * The 8-bit value to convert * @return Returns the 64-bit converted value * */ protected static long byteToLong(byte b) { return (b < 0) ? 256 + (long) b : (long) b; } /** * Used to determine if the ASN.1 type is a constructor. * * @param b * The ASN.1 type * * @return True if the ASN.1 type is a constructor, otherwise a false is * returned. * */ protected static boolean isConstructor(byte b) { return ((b & CONSTRUCTOR) == CONSTRUCTOR); } /** * Used to test if the ASN.1 type is an extension. * * @param b * The ASN.1 type. * * @return True if the ASN.1 type is an extension. False if the ASN.1 type * is not an extension. * */ protected static boolean isExtensionId(byte b) { return ((b & EXTENSION_ID) == EXTENSION_ID); } /** * Used to copy data from one buffer to another. The method has the * flexability to allow the caller to specify an offset in each buffer and * the total number of bytes to copy * * @param src * The source buffer * @param srcOff * The offset of the first byte in the source buffer * @param dest * The destination buffer * @param destOff * The offset of the first byte in the destination buffer * @param bytesToCopy * The number of bytes to copy * * @exception ArrayIndexOutOfBoundsException * Thrown if there is insufficent space in either array to * copy the data. * */ protected static void copy(byte[] src, int srcOff, byte[] dest, int destOff, int bytesToCopy) throws ArrayIndexOutOfBoundsException { if ((dest.length - destOff) < bytesToCopy || (src.length - srcOff) < bytesToCopy) throw new ArrayIndexOutOfBoundsException("Destination or source buffer is insufficent"); for (int x = bytesToCopy - 1; x >= 0; x--) { dest[destOff + x] = src[srcOff + x]; } } /** * Used to copy data from one buffer to another. The method has the * flexability to allow the caller to specify an offset in each buffer and * the total number of integers to copy * * @param src * The source buffer * @param srcOff * The offset of the first integer in the source buffer * @param dest * The destination buffer * @param destOff * The offset of the first integer in the destination buffer * @param intsToCopy * The number of integer elements to copy * * @exception ArrayIndexOutOfBoundsException * Thrown if there is insufficent space in either array to * copy the data. * */ protected static void copy(int[] src, int srcOff, int[] dest, int destOff, int intsToCopy) throws ArrayIndexOutOfBoundsException { if ((dest.length - destOff) < intsToCopy || (src.length - srcOff) < intsToCopy) throw new ArrayIndexOutOfBoundsException("Destination or source buffer is insufficent"); for (int x = intsToCopy - 1; x >= 0; x--) { dest[destOff + x] = src[srcOff + x]; } } /** * Rotates a give buffer area marked by begin, pivot, and end. The pivot * marks the point where the bytes between [pivot..end) are moved to the * position marked by begin. The bytes between [begin..pivot) are shifted * such that begin is at [begin+(end-pivot)]. * * @param buf * The buffer containing the data to rotate * @param begin * The start of the rotation * @param pivot * The pivot point for the rotation * @param end * The end of the rotational buffer * * @exception ArrayIndexOutOfBoundsException * Thrown if an access exception occurs * */ protected static void rotate(byte[] buf, int begin, int pivot, int end) throws ArrayIndexOutOfBoundsException { int dist = end - pivot; byte[] hold = new byte[dist]; copy(buf, // source pivot, // source offset hold, // destination 0, // destination offset dist); // length // // shift from end of buffer to front. This // way we do not have to worry about data // corruption // for (int x = (pivot - begin) - 1; x >= 0; x--) { buf[begin + dist + x] = buf[begin + x]; // SHIFT! } copy(hold, // source 0, // source offset buf, // destination begin, // destination offset dist); // length } /** * Default constructor for the BER Encoder. * */ public BerEncoder() { // default class constructor. // Does nothing } /** * * The buildLength() method is used to encode an ASN.1 length into the * specified byte buffer. The method is defined in the AsnEncoder interface. * * @param buf * The output buffer of encoded bytes. * @param startOffset * The offset from the start of the buffer where the method * should start writing the encoded data. * @param asnLength * The length to be encoded. * * @return Returns the new offset for the next encoding routine. If the * startOffset is subtracted from the return value then the length * of the encoded data can be determined. * * @exception AsnEncodingException * Thrown if an error occurs encoding the datatype. */ public int buildLength(byte[] buf, int startOffset, int asnLength) throws AsnEncodingException { if (asnLength <= 0x7f) { // // check the buffer length // if ((buf.length - startOffset) < 1) throw new AsnEncodingException("Buffer overflow error"); buf[startOffset++] = (byte) (asnLength & 0x7f); } else if (asnLength <= 0xff) { // // check the buffer length // if ((buf.length - startOffset) < 2) throw new AsnEncodingException("Buffer overflow error"); buf[startOffset++] = (byte) (0x01 | LONG_LENGTH); buf[startOffset++] = (byte) (asnLength & 0xff); } else // 0xff < asnLength <= 0xffff { // // check the buffer length // if ((buf.length - startOffset) < 3) throw new AsnEncodingException("Buffer overflow error"); buf[startOffset++] = (byte) (0x02 | LONG_LENGTH); buf[startOffset++] = (byte) ((asnLength >>> 8) & 0xff); buf[startOffset++] = (byte) (asnLength & 0xff); } return startOffset; } /** * * The parseLength() method is used to decode an ASN.1 length from the * specified buffer. The method is defined to support the AsnEncoder * interface. * * @param buf * The input buffer * @param startOffset * The offset to start decoding in the buffer * * @return Returns an Object array that contains the new offset and the * decoded length. The first object is an Integer object and * contains the new offset for the next object in buf. The second * object is an Integer and contains the actual decoded length. * * @exception AsnDecodingException * Thrown if an error occurs decoding the buffer. */ public Object[] parseLength(byte[] buf, int startOffset) throws AsnDecodingException { // // check the buffer length // if ((buf.length - startOffset) < 1) throw new AsnDecodingException("Buffer underflow error"); // // 1) Integer w/new offset value // 2) Integer w/recovered length // Object[] retVals = new Object[2]; // // get the first byte and check it for // the long length field // byte numBytes = buf[startOffset++]; if ((numBytes & LONG_LENGTH) == 0) { // // short definiate length encoding // numBytes = (byte) (numBytes & ~LONG_LENGTH); retVals[1] = new Integer(byteToInt(numBytes)); } else { // // Long length encoding // numBytes = (byte) (numBytes & ~LONG_LENGTH); if (numBytes == 1) { if ((buf.length - startOffset) < 1) throw new AsnDecodingException("Buffer underflow error"); retVals[1] = new Integer(byteToInt(buf[startOffset++])); } else if (numBytes == 2) { if ((buf.length - startOffset) < 2) throw new AsnDecodingException("Buffer underflow error"); int val = byteToInt(buf[startOffset++]) << 8 | byteToInt(buf[startOffset++]); retVals[1] = new Integer(val); } else { throw new AsnDecodingException("Invalid ASN.1 length"); } } // // create the offset object // retVals[0] = new Integer(startOffset); return retVals; } /** * * The buildHeader() method is used to encode an ASN.1 header into the * specified byte buffer. The method is defined to support the AsnEncoder * interface. This method is dependant on the buildLength() method. * * @param buf * The output buffer of encoded bytes. * @param startOffset * The offset from the start of the buffer where the method * should start writing the encoded data. * @param asnType * The ASN.1 type to place in the buffer * @param asnLength * The length to be encoded. * * @return Returns the new offset for the next encoding routine. If * startOffset is subtracted from the return value then the length * of the encoded data can be determined. * * @exception AsnEncodingException * Thrown if an error occurs encoding the datatype. * */ public int buildHeader(byte[] buf, int startOffset, byte asnType, int asnLength) throws AsnEncodingException { if ((buf.length - startOffset) < 1) throw new AsnEncodingException("Buffer overflow error"); buf[startOffset++] = asnType; return buildLength(buf, startOffset, asnLength); } /** * * The parseHeader() method is used to decode an ASN.1 header from the * specified buffer. The method is defined to support the AsnEncoder * interface. The method also calls the parseLength() method. * * @param buf * The input buffer * @param startOffset * The offset to start decoding in the buffer * * @return Returns an Object array that contains the new offset, ASN.1 type, * and decoded length. The first object is an Integer object and * contains the new offset for the next object in buf. The second * object is a Byte object that represents the decoded ASN.1 Type. * The third object is an Integer and contains the actual decoded * length. * * @exception AsnDecodingException * Thrown if an error occurs decoding the buffer. */ public Object[] parseHeader(byte[] buf, int startOffset) throws AsnDecodingException { if ((buf.length - startOffset) < 1) throw new AsnDecodingException("Insufficent buffer length"); // // get the ASN.1 Type // byte asnType = buf[startOffset++]; if (isExtensionId(asnType)) throw new AsnDecodingException("Buffer underflow error"); // // get the length // Object[] lenVals = parseLength(buf, startOffset);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?