src/jdk.dns.client/share/classes/jdk/dns/client/internal/Header.java
branchaefimov-dns-client-branch
changeset 58870 35c438a6d45c
child 58971 465a15dd6bed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.dns.client/share/classes/jdk/dns/client/internal/Header.java	Thu Oct 31 16:16:21 2019 +0000
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.dns.client.internal;
+
+import jdk.dns.client.ex.DnsResolverException;
+
+class Header {
+
+    static final int HEADER_SIZE = 12;  // octets in a DNS header
+
+    // Masks and shift amounts for DNS header flag fields.
+    static final short QR_BIT = (short) 0x8000;
+    static final short OPCODE_MASK = (short) 0x7800;
+    static final int OPCODE_SHIFT = 11;
+    static final short AA_BIT = (short) 0x0400;
+    static final short TC_BIT = (short) 0x0200;
+    static final short RD_BIT = (short) 0x0100;
+    static final short RA_BIT = (short) 0x0080;
+    static final short RCODE_MASK = (short) 0x000F;
+
+    int xid;                    // ID:  16-bit query identifier
+    boolean query;              // QR:  true if query, false if response
+    int opcode;                 // OPCODE:  4-bit opcode
+    boolean authoritative;      // AA
+    boolean truncated;          // TC
+    boolean recursionDesired;   // RD
+    boolean recursionAvail;     // RA
+    int rcode;                  // RCODE:  4-bit response code
+    int numQuestions;
+    int numAnswers;
+    int numAuthorities;
+    int numAdditionals;
+
+    /*
+     * Returns a representation of a decoded DNS message header.
+     * Does not modify or store a reference to the msg array.
+     */
+    Header(byte[] msg, int msgLen) throws DnsResolverException {
+        decode(msg, msgLen);
+    }
+
+    /*
+     * Decodes a DNS message header.  Does not modify or store a
+     * reference to the msg array.
+     */
+    private void decode(byte[] msg, int msgLen) throws DnsResolverException {
+
+        try {
+            int pos = 0;        // current offset into msg
+
+            if (msgLen < HEADER_SIZE) {
+                throw new DnsResolverException(
+                        "DNS error: corrupted message header");
+            }
+
+            xid = getShort(msg, pos);
+            pos += 2;
+
+            // Flags
+            short flags = (short) getShort(msg, pos);
+            pos += 2;
+            query = (flags & QR_BIT) == 0;
+            opcode = (flags & OPCODE_MASK) >>> OPCODE_SHIFT;
+            authoritative = (flags & AA_BIT) != 0;
+            truncated = (flags & TC_BIT) != 0;
+            recursionDesired = (flags & RD_BIT) != 0;
+            recursionAvail = (flags & RA_BIT) != 0;
+            rcode = (flags & RCODE_MASK);
+
+            // RR counts
+            numQuestions = getShort(msg, pos);
+            pos += 2;
+            numAnswers = getShort(msg, pos);
+            pos += 2;
+            numAuthorities = getShort(msg, pos);
+            pos += 2;
+            numAdditionals = getShort(msg, pos);
+            pos += 2;
+
+        } catch (IndexOutOfBoundsException e) {
+            throw new DnsResolverException("DNS error: corrupted message header");
+        }
+    }
+
+    /*
+     * Returns the 2-byte unsigned value at msg[pos].  The high
+     * order byte comes first.
+     */
+    private static int getShort(byte[] msg, int pos) {
+        return (((msg[pos] & 0xFF) << 8) |
+                (msg[pos + 1] & 0xFF));
+    }
+}