Question.java

  1package de.measite.minidns;
  2
  3import java.io.ByteArrayOutputStream;
  4import java.io.DataInputStream;
  5import java.io.DataOutputStream;
  6import java.io.IOException;
  7import java.util.Arrays;
  8
  9import de.measite.minidns.Record.CLASS;
 10import de.measite.minidns.Record.TYPE;
 11import de.measite.minidns.util.NameUtil;
 12
 13/**
 14 * A DNS question (request).
 15 */
 16public class Question {
 17
 18    /**
 19     * The question string (e.g. "measite.de").
 20     */
 21    private final String name;
 22
 23    /**
 24     * The question type (e.g. A).
 25     */
 26    private final TYPE type;
 27
 28    /**
 29     * The question class (usually IN / internet).
 30     */
 31    private final CLASS clazz;
 32
 33    /**
 34     * Cache for the serialized object.
 35     */
 36    private byte[] byteArray;
 37
 38    /**
 39     * Create a dns question for the given name/type/class.
 40     * @param name The name e.g. "measite.de".
 41     * @param type The type, e.g. A.
 42     * @param clazz The class, usually IN (internet).
 43     */
 44    public Question(String name, TYPE type, CLASS clazz) {
 45        this.name = name;
 46        this.type = type;
 47        this.clazz = clazz;
 48    }
 49
 50    /**
 51     * Create a dns question for the given name/type/IN (internet class).
 52     * @param name The name e.g. "measite.de".
 53     * @param type The type, e.g. A.
 54     */
 55    public Question(String name, TYPE type) {
 56        this(name, type, CLASS.IN);
 57    }
 58
 59    /**
 60     * Retrieve the type of this question.
 61     * @return The type.
 62     */
 63    public TYPE getType() {
 64        return type;
 65    }
 66
 67    /**
 68     * Retrieve the class of this dns question (usually internet).
 69     * @return The class of this dns question.
 70     */
 71    public CLASS getClazz() {
 72        return clazz;
 73    }
 74
 75    /**
 76     * Retrieve the name of this dns question (e.g. "measite.de").
 77     * @return The name of this dns question.
 78     */
 79    public String getName() {
 80        return name;
 81    }
 82
 83    /**
 84     * Parse a byte array and rebuild the dns question from it.
 85     * @param dis The input stream.
 86     * @param data The plain data (for dns name references).
 87     * @return The parsed dns question.
 88     * @throws IOException On errors (read outside of packet).
 89     */
 90    public static Question parse(DataInputStream dis, byte[] data) throws IOException {
 91        String name = NameUtil.parse(dis, data);
 92        TYPE type = TYPE.getType(dis.readUnsignedShort());
 93        CLASS clazz = CLASS.getClass(dis.readUnsignedShort());
 94        return new Question (name, type, clazz);
 95    }
 96
 97    /**
 98     * Generate a binary paket for this dns question.
 99     * @return The dns question.
100     */
101    public byte[] toByteArray() {
102        if (byteArray == null) {
103            ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
104            DataOutputStream dos = new DataOutputStream(baos);
105
106            try {
107                dos.write(NameUtil.toByteArray(this.name));
108                dos.writeShort(type.getValue());
109                dos.writeShort(clazz.getValue());
110                dos.flush();
111            } catch (IOException e) {
112                // Should never happen
113                throw new IllegalStateException(e);
114            }
115            byteArray = baos.toByteArray();
116        }
117        return byteArray;
118    }
119
120    @Override
121    public int hashCode() {
122        return Arrays.hashCode(toByteArray());
123    }
124
125    @Override
126    public boolean equals(Object other) {
127        if (this == other) {
128            return true;
129        }
130        if (!(other instanceof Question)) {
131            return false;
132        }
133        byte t[] = toByteArray();
134        byte o[] = ((Question)other).toByteArray();
135        return Arrays.equals(t, o);
136    }
137}