• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
2 
3 package org.xbill.DNS;
4 
5 /**
6  * A class for rendering DNS messages.
7  *
8  * @author Brian Wellington
9  */
10 
11 
12 public class DNSOutput {
13 
14 private byte [] array;
15 private int pos;
16 private int saved_pos;
17 
18 /**
19  * Create a new DNSOutput with a specified size.
20  * @param size The initial size
21  */
22 public
DNSOutput(int size)23 DNSOutput(int size) {
24 	array = new byte[size];
25 	pos = 0;
26 	saved_pos = -1;
27 }
28 
29 /**
30  * Create a new DNSOutput
31  */
32 public
DNSOutput()33 DNSOutput() {
34 	this(32);
35 }
36 
37 /**
38  * Returns the current position.
39  */
40 public int
current()41 current() {
42 	return pos;
43 }
44 
45 private void
check(long val, int bits)46 check(long val, int bits) {
47 	long max = 1;
48 	max <<= bits;
49 	if (val < 0 || val > max) {
50 		throw new IllegalArgumentException(val + " out of range for " +
51 						   bits + " bit value");
52 	}
53 }
54 
55 private void
need(int n)56 need(int n) {
57 	if (array.length - pos >= n) {
58 		return;
59 	}
60 	int newsize = array.length * 2;
61 	if (newsize < pos + n) {
62 		newsize = pos + n;
63 	}
64 	byte [] newarray = new byte[newsize];
65 	System.arraycopy(array, 0, newarray, 0, pos);
66 	array = newarray;
67 }
68 
69 /**
70  * Resets the current position of the output stream to the specified index.
71  * @param index The new current position.
72  * @throws IllegalArgumentException The index is not within the output.
73  */
74 public void
jump(int index)75 jump(int index) {
76 	if (index > pos) {
77 		throw new IllegalArgumentException("cannot jump past " +
78 						   "end of data");
79 	}
80 	pos = index;
81 }
82 
83 /**
84  * Saves the current state of the output stream.
85  * @throws IllegalArgumentException The index is not within the output.
86  */
87 public void
save()88 save() {
89 	saved_pos = pos;
90 }
91 
92 /**
93  * Restores the input stream to its state before the call to {@link #save}.
94  */
95 public void
restore()96 restore() {
97 	if (saved_pos < 0) {
98 		throw new IllegalStateException("no previous state");
99 	}
100 	pos = saved_pos;
101 	saved_pos = -1;
102 }
103 
104 /**
105  * Writes an unsigned 8 bit value to the stream.
106  * @param val The value to be written
107  */
108 public void
writeU8(int val)109 writeU8(int val) {
110 	check(val, 8);
111 	need(1);
112 	array[pos++] = (byte)(val & 0xFF);
113 }
114 
115 /**
116  * Writes an unsigned 16 bit value to the stream.
117  * @param val The value to be written
118  */
119 public void
writeU16(int val)120 writeU16(int val) {
121 	check(val, 16);
122 	need(2);
123 	array[pos++] = (byte)((val >>> 8) & 0xFF);
124 	array[pos++] = (byte)(val & 0xFF);
125 }
126 
127 /**
128  * Writes an unsigned 16 bit value to the specified position in the stream.
129  * @param val The value to be written
130  * @param where The position to write the value.
131  */
132 public void
writeU16At(int val, int where)133 writeU16At(int val, int where) {
134 	check(val, 16);
135 	if (where > pos - 2)
136 		throw new IllegalArgumentException("cannot write past " +
137 						   "end of data");
138 	array[where++] = (byte)((val >>> 8) & 0xFF);
139 	array[where++] = (byte)(val & 0xFF);
140 }
141 
142 /**
143  * Writes an unsigned 32 bit value to the stream.
144  * @param val The value to be written
145  */
146 public void
writeU32(long val)147 writeU32(long val) {
148 	check(val, 32);
149 	need(4);
150 	array[pos++] = (byte)((val >>> 24) & 0xFF);
151 	array[pos++] = (byte)((val >>> 16) & 0xFF);
152 	array[pos++] = (byte)((val >>> 8) & 0xFF);
153 	array[pos++] = (byte)(val & 0xFF);
154 }
155 
156 /**
157  * Writes a byte array to the stream.
158  * @param b The array to write.
159  * @param off The offset of the array to start copying data from.
160  * @param len The number of bytes to write.
161  */
162 public void
writeByteArray(byte [] b, int off, int len)163 writeByteArray(byte [] b, int off, int len) {
164 	need(len);
165 	System.arraycopy(b, off, array, pos, len);
166 	pos += len;
167 }
168 
169 /**
170  * Writes a byte array to the stream.
171  * @param b The array to write.
172  */
173 public void
writeByteArray(byte [] b)174 writeByteArray(byte [] b) {
175 	writeByteArray(b, 0, b.length);
176 }
177 
178 /**
179  * Writes a counted string from the stream.  A counted string is a one byte
180  * value indicating string length, followed by bytes of data.
181  * @param s The string to write.
182  */
183 public void
writeCountedString(byte [] s)184 writeCountedString(byte [] s) {
185 	if (s.length > 0xFF) {
186 		throw new IllegalArgumentException("Invalid counted string");
187 	}
188 	need(1 + s.length);
189 	array[pos++] = (byte)(s.length & 0xFF);
190 	writeByteArray(s, 0, s.length);
191 }
192 
193 /**
194  * Returns a byte array containing the current contents of the stream.
195  */
196 public byte []
toByteArray()197 toByteArray() {
198 	byte [] out = new byte[pos];
199 	System.arraycopy(array, 0, out, 0, pos);
200 	return out;
201 }
202 
203 }
204