blob: d3134ed872c9b7c0c378e6928d8de57472df25b9 [file] [log] [blame]
Shuyi Chend7955ce2013-05-22 14:51:55 -07001// Copyright (c) 2004 Brian Wellington (bwelling@xbill.org)
2
3package org.xbill.DNS;
4
5/**
6 * An class for parsing DNS messages.
7 *
8 * @author Brian Wellington
9 */
10
11public class DNSInput {
12
13private byte [] array;
14private int pos;
15private int end;
16private int saved_pos;
17private int saved_end;
18
19/**
20 * Creates a new DNSInput
21 * @param input The byte array to read from
22 */
23public
24DNSInput(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 */
35public int
36current() {
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 */
44public int
45remaining() {
46 return end - pos;
47}
48
49private void
50require(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 */
62public void
63setActive(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 */
75public void
76clearActive() {
77 end = array.length;
78}
79
80/**
81 * Returns the position of the end of the current active region.
82 */
83public int
84saveActive() {
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 */
94public void
95restoreActive(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 */
109public void
110jump(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 */
124public void
125save() {
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 */
133public void
134restore() {
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 */
149public int
150readU8() 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 */
160public int
161readU16() 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 */
173public long
174readU32() 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 */
191public void
192readByteArray(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 */
203public byte []
204readByteArray(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 */
217public byte []
218readByteArray() {
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 */
232public byte []
233readCountedString() throws WireParseException {
234 require(1);
235 int len = array[pos++] & 0xFF;
236 return readByteArray(len);
237}
238
239}