aboutsummaryrefslogtreecommitdiff
path: root/src/org/xbill/DNS/DNSInput.java
blob: d3134ed872c9b7c0c378e6928d8de57472df25b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
// Copyright (c) 2004 Brian Wellington (bwelling@xbill.org)

package org.xbill.DNS;

/**
 * An class for parsing DNS messages.
 *
 * @author Brian Wellington
 */

public class DNSInput {

private byte [] array;
private int pos;
private int end;
private int saved_pos;
private int saved_end;

/**
 * Creates a new DNSInput
 * @param input The byte array to read from
 */
public
DNSInput(byte [] input) {
	array = input;
	pos = 0;
	end = array.length;
	saved_pos = -1;
	saved_end = -1;
}

/**
 * Returns the current position.
 */
public int
current() {
	return pos;
}

/**
 * Returns the number of bytes that can be read from this stream before
 * reaching the end.
 */
public int
remaining() {
	return end - pos;
}

private void
require(int n) throws WireParseException{
	if (n > remaining()) {
		throw new WireParseException("end of input");
	}
}

/**
 * Marks the following bytes in the stream as active.
 * @param len The number of bytes in the active region.
 * @throws IllegalArgumentException The number of bytes in the active region
 * is longer than the remainder of the input.
 */
public void
setActive(int len) {
	if (len > array.length - pos) {
		throw new IllegalArgumentException("cannot set active " +
						   "region past end of input");
	}
	end = pos + len;
}

/**
 * Clears the active region of the string.  Further operations are not
 * restricted to part of the input.
 */
public void
clearActive() {
	end = array.length;
}

/**
 * Returns the position of the end of the current active region.
 */
public int
saveActive() {
	return end;
}

/**
 * Restores the previously set active region.  This differs from setActive() in
 * that restoreActive() takes an absolute position, and setActive takes an
 * offset from the current location.
 * @param pos The end of the active region.
 */
public void
restoreActive(int pos) {
	if (pos > array.length) {
		throw new IllegalArgumentException("cannot set active " +
						   "region past end of input");
	}
	end = pos;
}

/**
 * Resets the current position of the input stream to the specified index,
 * and clears the active region.
 * @param index The position to continue parsing at.
 * @throws IllegalArgumentException The index is not within the input.
 */
public void
jump(int index) {
	if (index >= array.length) {
		throw new IllegalArgumentException("cannot jump past " +
						   "end of input");
	}
	pos = index;
	end = array.length;
}

/**
 * Saves the current state of the input stream.  Both the current position and
 * the end of the active region are saved.
 * @throws IllegalArgumentException The index is not within the input.
 */
public void
save() {
	saved_pos = pos;
	saved_end = end;
}

/**
 * Restores the input stream to its state before the call to {@link #save}.
 */
public void
restore() {
	if (saved_pos < 0) {
		throw new IllegalStateException("no previous state");
	}
	pos = saved_pos;
	end = saved_end;
	saved_pos = -1;
	saved_end = -1;
}

/**
 * Reads an unsigned 8 bit value from the stream, as an int.
 * @return An unsigned 8 bit value.
 * @throws WireParseException The end of the stream was reached.
 */
public int
readU8() throws WireParseException {
	require(1);
	return (array[pos++] & 0xFF);
}

/**
 * Reads an unsigned 16 bit value from the stream, as an int.
 * @return An unsigned 16 bit value.
 * @throws WireParseException The end of the stream was reached.
 */
public int
readU16() throws WireParseException {
	require(2);
	int b1 = array[pos++] & 0xFF;
	int b2 = array[pos++] & 0xFF;
	return ((b1 << 8) + b2);
}

/**
 * Reads an unsigned 32 bit value from the stream, as a long.
 * @return An unsigned 32 bit value.
 * @throws WireParseException The end of the stream was reached.
 */
public long
readU32() throws WireParseException {
	require(4);
	int b1 = array[pos++] & 0xFF;
	int b2 = array[pos++] & 0xFF;
	int b3 = array[pos++] & 0xFF;
	int b4 = array[pos++] & 0xFF;
	return (((long)b1 << 24) + (b2 << 16) + (b3 << 8) + b4);
}

/**
 * Reads a byte array of a specified length from the stream into an existing
 * array.
 * @param b The array to read into.
 * @param off The offset of the array to start copying data into.
 * @param len The number of bytes to copy.
 * @throws WireParseException The end of the stream was reached.
 */
public void
readByteArray(byte [] b, int off, int len) throws WireParseException {
	require(len);
	System.arraycopy(array, pos, b, off, len);
	pos += len;
}

/**
 * Reads a byte array of a specified length from the stream.
 * @return The byte array.
 * @throws WireParseException The end of the stream was reached.
 */
public byte []
readByteArray(int len) throws WireParseException {
	require(len);
	byte [] out = new byte[len];
	System.arraycopy(array, pos, out, 0, len);
	pos += len;
	return out;
}

/**
 * Reads a byte array consisting of the remainder of the stream (or the
 * active region, if one is set.
 * @return The byte array.
 */
public byte []
readByteArray() {
	int len = remaining();
	byte [] out = new byte[len];
	System.arraycopy(array, pos, out, 0, len);
	pos += len;
	return out;
}

/**
 * Reads a counted string from the stream.  A counted string is a one byte
 * value indicating string length, followed by bytes of data.
 * @return A byte array containing the string.
 * @throws WireParseException The end of the stream was reached.
 */
public byte []
readCountedString() throws WireParseException {
	require(1);
	int len = array[pos++] & 0xFF;
	return readByteArray(len);
}

}