Home | History | Annotate | Download | only in DNS
      1 // Copyright (c) 2004 Brian Wellington (bwelling (at) xbill.org)
      2 
      3 package org.xbill.DNS;
      4 
      5 /**
      6  * An class for parsing DNS messages.
      7  *
      8  * @author Brian Wellington
      9  */
     10 
     11 public class DNSInput {
     12 
     13 private byte [] array;
     14 private int pos;
     15 private int end;
     16 private int saved_pos;
     17 private int saved_end;
     18 
     19 /**
     20  * Creates a new DNSInput
     21  * @param input The byte array to read from
     22  */
     23 public
     24 DNSInput(byte [] input) {
     25 	array = input;
     26 	pos = 0;
     27 	end = array.length;
     28 	saved_pos = -1;
     29 	saved_end = -1;
     30 }
     31 
     32 /**
     33  * Returns the current position.
     34  */
     35 public int
     36 current() {
     37 	return pos;
     38 }
     39 
     40 /**
     41  * Returns the number of bytes that can be read from this stream before
     42  * reaching the end.
     43  */
     44 public int
     45 remaining() {
     46 	return end - pos;
     47 }
     48 
     49 private void
     50 require(int n) throws WireParseException{
     51 	if (n > remaining()) {
     52 		throw new WireParseException("end of input");
     53 	}
     54 }
     55 
     56 /**
     57  * Marks the following bytes in the stream as active.
     58  * @param len The number of bytes in the active region.
     59  * @throws IllegalArgumentException The number of bytes in the active region
     60  * is longer than the remainder of the input.
     61  */
     62 public void
     63 setActive(int len) {
     64 	if (len > array.length - pos) {
     65 		throw new IllegalArgumentException("cannot set active " +
     66 						   "region past end of input");
     67 	}
     68 	end = pos + len;
     69 }
     70 
     71 /**
     72  * Clears the active region of the string.  Further operations are not
     73  * restricted to part of the input.
     74  */
     75 public void
     76 clearActive() {
     77 	end = array.length;
     78 }
     79 
     80 /**
     81  * Returns the position of the end of the current active region.
     82  */
     83 public int
     84 saveActive() {
     85 	return end;
     86 }
     87 
     88 /**
     89  * Restores the previously set active region.  This differs from setActive() in
     90  * that restoreActive() takes an absolute position, and setActive takes an
     91  * offset from the current location.
     92  * @param pos The end of the active region.
     93  */
     94 public void
     95 restoreActive(int pos) {
     96 	if (pos > array.length) {
     97 		throw new IllegalArgumentException("cannot set active " +
     98 						   "region past end of input");
     99 	}
    100 	end = pos;
    101 }
    102 
    103 /**
    104  * Resets the current position of the input stream to the specified index,
    105  * and clears the active region.
    106  * @param index The position to continue parsing at.
    107  * @throws IllegalArgumentException The index is not within the input.
    108  */
    109 public void
    110 jump(int index) {
    111 	if (index >= array.length) {
    112 		throw new IllegalArgumentException("cannot jump past " +
    113 						   "end of input");
    114 	}
    115 	pos = index;
    116 	end = array.length;
    117 }
    118 
    119 /**
    120  * Saves the current state of the input stream.  Both the current position and
    121  * the end of the active region are saved.
    122  * @throws IllegalArgumentException The index is not within the input.
    123  */
    124 public void
    125 save() {
    126 	saved_pos = pos;
    127 	saved_end = end;
    128 }
    129 
    130 /**
    131  * Restores the input stream to its state before the call to {@link #save}.
    132  */
    133 public void
    134 restore() {
    135 	if (saved_pos < 0) {
    136 		throw new IllegalStateException("no previous state");
    137 	}
    138 	pos = saved_pos;
    139 	end = saved_end;
    140 	saved_pos = -1;
    141 	saved_end = -1;
    142 }
    143 
    144 /**
    145  * Reads an unsigned 8 bit value from the stream, as an int.
    146  * @return An unsigned 8 bit value.
    147  * @throws WireParseException The end of the stream was reached.
    148  */
    149 public int
    150 readU8() throws WireParseException {
    151 	require(1);
    152 	return (array[pos++] & 0xFF);
    153 }
    154 
    155 /**
    156  * Reads an unsigned 16 bit value from the stream, as an int.
    157  * @return An unsigned 16 bit value.
    158  * @throws WireParseException The end of the stream was reached.
    159  */
    160 public int
    161 readU16() throws WireParseException {
    162 	require(2);
    163 	int b1 = array[pos++] & 0xFF;
    164 	int b2 = array[pos++] & 0xFF;
    165 	return ((b1 << 8) + b2);
    166 }
    167 
    168 /**
    169  * Reads an unsigned 32 bit value from the stream, as a long.
    170  * @return An unsigned 32 bit value.
    171  * @throws WireParseException The end of the stream was reached.
    172  */
    173 public long
    174 readU32() throws WireParseException {
    175 	require(4);
    176 	int b1 = array[pos++] & 0xFF;
    177 	int b2 = array[pos++] & 0xFF;
    178 	int b3 = array[pos++] & 0xFF;
    179 	int b4 = array[pos++] & 0xFF;
    180 	return (((long)b1 << 24) + (b2 << 16) + (b3 << 8) + b4);
    181 }
    182 
    183 /**
    184  * Reads a byte array of a specified length from the stream into an existing
    185  * array.
    186  * @param b The array to read into.
    187  * @param off The offset of the array to start copying data into.
    188  * @param len The number of bytes to copy.
    189  * @throws WireParseException The end of the stream was reached.
    190  */
    191 public void
    192 readByteArray(byte [] b, int off, int len) throws WireParseException {
    193 	require(len);
    194 	System.arraycopy(array, pos, b, off, len);
    195 	pos += len;
    196 }
    197 
    198 /**
    199  * Reads a byte array of a specified length from the stream.
    200  * @return The byte array.
    201  * @throws WireParseException The end of the stream was reached.
    202  */
    203 public byte []
    204 readByteArray(int len) throws WireParseException {
    205 	require(len);
    206 	byte [] out = new byte[len];
    207 	System.arraycopy(array, pos, out, 0, len);
    208 	pos += len;
    209 	return out;
    210 }
    211 
    212 /**
    213  * Reads a byte array consisting of the remainder of the stream (or the
    214  * active region, if one is set.
    215  * @return The byte array.
    216  */
    217 public byte []
    218 readByteArray() {
    219 	int len = remaining();
    220 	byte [] out = new byte[len];
    221 	System.arraycopy(array, pos, out, 0, len);
    222 	pos += len;
    223 	return out;
    224 }
    225 
    226 /**
    227  * Reads a counted string from the stream.  A counted string is a one byte
    228  * value indicating string length, followed by bytes of data.
    229  * @return A byte array containing the string.
    230  * @throws WireParseException The end of the stream was reached.
    231  */
    232 public byte []
    233 readCountedString() throws WireParseException {
    234 	require(1);
    235 	int len = array[pos++] & 0xFF;
    236 	return readByteArray(len);
    237 }
    238 
    239 }
    240