• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2004 Brian Wellington (bwelling@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
DNSInput(byte [] input)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
current()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
remaining()45 remaining() {
46 	return end - pos;
47 }
48 
49 private void
require(int n)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
setActive(int len)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
clearActive()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
saveActive()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
restoreActive(int pos)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
jump(int index)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
save()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
restore()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
readU8()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
readU16()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
readU32()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
readByteArray(byte [] b, int off, int len)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 []
readByteArray(int len)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 []
readByteArray()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 []
readCountedString()233 readCountedString() throws WireParseException {
234 	require(1);
235 	int len = array[pos++] & 0xFF;
236 	return readByteArray(len);
237 }
238 
239 }
240