// /Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL

package javax.jmdns.impl;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSLabel;
import javax.jmdns.impl.constants.DNSOptionCode;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
import javax.jmdns.impl.constants.DNSResultCode;

/**
 * Parse an incoming DNS message into its components.
 *
 * @author Arthur van Hoff, Werner Randelshofer, Pierre Frisch, Daniel Bobbert
 */
public final class DNSIncoming extends DNSMessage {
    private static Logger logger                                = Logger.getLogger(DNSIncoming.class.getName());

    // This is a hack to handle a bug in the BonjourConformanceTest
    // It is sending out target strings that don't follow the "domain name" format.
    public static boolean USE_DOMAIN_NAME_FORMAT_FOR_SRV_TARGET = true;

    public static class MessageInputStream extends ByteArrayInputStream {
        private static Logger      logger1 = Logger.getLogger(MessageInputStream.class.getName());

        final Map<Integer, String> _names;

        public MessageInputStream(byte[] buffer, int length) {
            this(buffer, 0, length);
        }

        /**
         * @param buffer
         * @param offset
         * @param length
         */
        public MessageInputStream(byte[] buffer, int offset, int length) {
            super(buffer, offset, length);
            _names = new HashMap<Integer, String>();
        }

        public int readByte() {
            return this.read();
        }

        public int readUnsignedShort() {
            return (this.read() << 8) | this.read();
        }

        public int readInt() {
            return (this.readUnsignedShort() << 16) | this.readUnsignedShort();
        }

        public byte[] readBytes(int len) {
            byte bytes[] = new byte[len];
            this.read(bytes, 0, len);
            return bytes;
        }

        public String readUTF(int len) {
            StringBuilder buffer = new StringBuilder(len);
            for (int index = 0; index < len; index++) {
                int ch = this.read();
                switch (ch >> 4) {
                    case 0:
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                        // 0xxxxxxx
                        break;
                    case 12:
                    case 13:
                        // 110x xxxx 10xx xxxx
                        ch = ((ch & 0x1F) << 6) | (this.read() & 0x3F);
                        index++;
                        break;
                    case 14:
                        // 1110 xxxx 10xx xxxx 10xx xxxx
                        ch = ((ch & 0x0f) << 12) | ((this.read() & 0x3F) << 6) | (this.read() & 0x3F);
                        index++;
                        index++;
                        break;
                    default:
                        // 10xx xxxx, 1111 xxxx
                        ch = ((ch & 0x3F) << 4) | (this.read() & 0x0f);
                        index++;
                        break;
                }
                buffer.append((char) ch);
            }
            return buffer.toString();
        }

        protected synchronized int peek() {
            return (pos < count) ? (buf[pos] & 0xff) : -1;
        }

        public String readName() {
            Map<Integer, StringBuilder> names = new HashMap<Integer, StringBuilder>();
            StringBuilder buffer = new StringBuilder();
            boolean finished = false;
            while (!finished) {
                int len = this.read();
                if (len == 0) {
                    finished = true;
                    break;
                }
                switch (DNSLabel.labelForByte(len)) {
                    case Standard:
                        int offset = pos - 1;
                        String label = this.readUTF(len) + ".";
                        buffer.append(label);
                        for (StringBuilder previousLabel : names.values()) {
                            previousLabel.append(label);
                        }
                        names.put(Integer.valueOf(offset), new StringBuilder(label));
                        break;
                    case Compressed:
                        int index = (DNSLabel.labelValue(len) << 8) | this.read();
                        String compressedLabel = _names.get(Integer.valueOf(index));
                        if (compressedLabel == null) {
                            logger1.severe("bad domain name: possible circular name detected. Bad offset: 0x" + Integer.toHexString(index) + " at 0x" + Integer.toHexString(pos - 2));
                            compressedLabel = "";
                        }
                        buffer.append(compressedLabel);
                        for (StringBuilder previousLabel : names.values()) {
                            previousLabel.append(compressedLabel);
                        }
                        finished = true;
                        break;
                    case Extended:
                        // int extendedLabelClass = DNSLabel.labelValue(len);
                        logger1.severe("Extended label are not currently supported.");
                        break;
                    case Unknown:
                    default:
                        logger1.severe("unsupported dns label type: '" + Integer.toHexString(len & 0xC0) + "'");
                }
            }
            for (Integer index : names.keySet()) {
                _names.put(index, names.get(index).toString());
            }
            return buffer.toString();
        }

        public String readNonNameString() {
            int len = this.read();
            return this.readUTF(len);
        }

    }

    private final DatagramPacket     _packet;

    private final long               _receivedTime;

    private final MessageInputStream _messageInputStream;

    private int                      _senderUDPPayload;

    /**
     * Parse a message from a datagram packet.
     *
     * @param packet
     * @exception IOException
     */
    public DNSIncoming(DatagramPacket packet) throws IOException {
        super(0, 0, packet.getPort() == DNSConstants.MDNS_PORT);
        this._packet = packet;
        InetAddress source = packet.getAddress();
        this._messageInputStream = new MessageInputStream(packet.getData(), packet.getLength());
        this._receivedTime = System.currentTimeMillis();
        this._senderUDPPayload = DNSConstants.MAX_MSG_TYPICAL;

        try {
            this.setId(_messageInputStream.readUnsignedShort());
            this.setFlags(_messageInputStream.readUnsignedShort());
            int numQuestions = _messageInputStream.readUnsignedShort();
            int numAnswers = _messageInputStream.readUnsignedShort();
            int numAuthorities = _messageInputStream.readUnsignedShort();
            int numAdditionals = _messageInputStream.readUnsignedShort();

            // parse questions
            if (numQuestions > 0) {
                for (int i = 0; i < numQuestions; i++) {
                    _questions.add(this.readQuestion());
                }
            }

            // parse answers
            if (numAnswers > 0) {
                for (int i = 0; i < numAnswers; i++) {
                    DNSRecord rec = this.readAnswer(source);
                    if (rec != null) {
                        // Add a record, if we were able to create one.
                        _answers.add(rec);
                    }
                }
            }

            if (numAuthorities > 0) {
                for (int i = 0; i < numAuthorities; i++) {
                    DNSRecord rec = this.readAnswer(source);
                    if (rec != null) {
                        // Add a record, if we were able to create one.
                        _authoritativeAnswers.add(rec);
                    }
                }
            }

            if (numAdditionals > 0) {
                for (int i = 0; i < numAdditionals; i++) {
                    DNSRecord rec = this.readAnswer(source);
                    if (rec != null) {
                        // Add a record, if we were able to create one.
                        _additionals.add(rec);
                    }
                }
            }
        } catch (Exception e) {
            logger.log(Level.WARNING, "DNSIncoming() dump " + print(true) + "\n exception ", e);
            // This ugly but some JVM don't implement the cause on IOException
            IOException ioe = new IOException("DNSIncoming corrupted message");
            ioe.initCause(e);
            throw ioe;
        }
    }

    private DNSIncoming(int flags, int id, boolean multicast, DatagramPacket packet, long receivedTime) {
        super(flags, id, multicast);
        this._packet = packet;
        this._messageInputStream = new MessageInputStream(packet.getData(), packet.getLength());
        this._receivedTime = receivedTime;
    }


    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#clone()
     */
    @Override
    public DNSIncoming clone() {
        DNSIncoming in = new DNSIncoming(this.getFlags(), this.getId(), this.isMulticast(), this._packet, this._receivedTime);
         in._senderUDPPayload = this._senderUDPPayload;
         in._questions.addAll(this._questions);
         in._answers.addAll(this._answers);
         in._authoritativeAnswers.addAll(this._authoritativeAnswers);
         in._additionals.addAll(this._additionals);
         return in;
    }


    private DNSQuestion readQuestion() {
        String domain = _messageInputStream.readName();
        DNSRecordType type = DNSRecordType.typeForIndex(_messageInputStream.readUnsignedShort());
        if (type == DNSRecordType.TYPE_IGNORE) {
            logger.log(Level.SEVERE, "Could not find record type: " + this.print(true));
        }
        int recordClassIndex = _messageInputStream.readUnsignedShort();
        DNSRecordClass recordClass = DNSRecordClass.classForIndex(recordClassIndex);
        boolean unique = recordClass.isUnique(recordClassIndex);
        return DNSQuestion.newQuestion(domain, type, recordClass, unique);
    }

    private DNSRecord readAnswer(InetAddress source) {
        String domain = _messageInputStream.readName();
        DNSRecordType type = DNSRecordType.typeForIndex(_messageInputStream.readUnsignedShort());
        if (type == DNSRecordType.TYPE_IGNORE) {
            logger.log(Level.SEVERE, "Could not find record type. domain: " + domain + "\n" + this.print(true));
        }
        int recordClassIndex = _messageInputStream.readUnsignedShort();
        DNSRecordClass recordClass = (type == DNSRecordType.TYPE_OPT ? DNSRecordClass.CLASS_UNKNOWN : DNSRecordClass.classForIndex(recordClassIndex));
        if ((recordClass == DNSRecordClass.CLASS_UNKNOWN) && (type != DNSRecordType.TYPE_OPT)) {
            logger.log(Level.SEVERE, "Could not find record class. domain: " + domain + " type: " + type + "\n" + this.print(true));
        }
        boolean unique = recordClass.isUnique(recordClassIndex);
        int ttl = _messageInputStream.readInt();
        int len = _messageInputStream.readUnsignedShort();
        DNSRecord rec = null;

        switch (type) {
            case TYPE_A: // IPv4
                rec = new DNSRecord.IPv4Address(domain, recordClass, unique, ttl, _messageInputStream.readBytes(len));
                break;
            case TYPE_AAAA: // IPv6
                rec = new DNSRecord.IPv6Address(domain, recordClass, unique, ttl, _messageInputStream.readBytes(len));
                break;
            case TYPE_CNAME:
            case TYPE_PTR:
                String service = "";
                service = _messageInputStream.readName();
                if (service.length() > 0) {
                    rec = new DNSRecord.Pointer(domain, recordClass, unique, ttl, service);
                } else {
                    logger.log(Level.WARNING, "PTR record of class: " + recordClass + ", there was a problem reading the service name of the answer for domain:" + domain);
                }
                break;
            case TYPE_TXT:
                rec = new DNSRecord.Text(domain, recordClass, unique, ttl, _messageInputStream.readBytes(len));
                break;
            case TYPE_SRV:
                int priority = _messageInputStream.readUnsignedShort();
                int weight = _messageInputStream.readUnsignedShort();
                int port = _messageInputStream.readUnsignedShort();
                String target = "";
                // This is a hack to handle a bug in the BonjourConformanceTest
                // It is sending out target strings that don't follow the "domain name" format.
                if (USE_DOMAIN_NAME_FORMAT_FOR_SRV_TARGET) {
                    target = _messageInputStream.readName();
                } else {
                    // [PJYF Nov 13 2010] Do we still need this? This looks really bad. All label are supposed to start by a length.
                    target = _messageInputStream.readNonNameString();
                }
                rec = new DNSRecord.Service(domain, recordClass, unique, ttl, priority, weight, port, target);
                break;
            case TYPE_HINFO:
                StringBuilder buf = new StringBuilder();
                buf.append(_messageInputStream.readUTF(len));
                int index = buf.indexOf(" ");
                String cpu = (index > 0 ? buf.substring(0, index) : buf.toString()).trim();
                String os = (index > 0 ? buf.substring(index + 1) : "").trim();
                rec = new DNSRecord.HostInformation(domain, recordClass, unique, ttl, cpu, os);
                break;
            case TYPE_OPT:
                DNSResultCode extendedResultCode = DNSResultCode.resultCodeForFlags(this.getFlags(), ttl);
                int version = (ttl & 0x00ff0000) >> 16;
                if (version == 0) {
                    _senderUDPPayload = recordClassIndex;
                    while (_messageInputStream.available() > 0) {
                        // Read RDData
                        int optionCodeInt = 0;
                        DNSOptionCode optionCode = null;
                        if (_messageInputStream.available() >= 2) {
                            optionCodeInt = _messageInputStream.readUnsignedShort();
                            optionCode = DNSOptionCode.resultCodeForFlags(optionCodeInt);
                        } else {
                            logger.log(Level.WARNING, "There was a problem reading the OPT record. Ignoring.");
                            break;
                        }
                        int optionLength = 0;
                        if (_messageInputStream.available() >= 2) {
                            optionLength = _messageInputStream.readUnsignedShort();
                        } else {
                            logger.log(Level.WARNING, "There was a problem reading the OPT record. Ignoring.");
                            break;
                        }
                        byte[] optiondata = new byte[0];
                        if (_messageInputStream.available() >= optionLength) {
                            optiondata = _messageInputStream.readBytes(optionLength);
                        }
                        //
                        // We should really do something with those options.
                        switch (optionCode) {
                            case Owner:
                                // Valid length values are 8, 14, 18 and 20
                                // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                                // |Opt|Len|V|S|Primary MAC|Wakeup MAC | Password |
                                // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                                //
                                int ownerVersion = 0;
                                int ownerSequence = 0;
                                byte[] ownerPrimaryMacAddress = null;
                                byte[] ownerWakeupMacAddress = null;
                                byte[] ownerPassword = null;
                                try {
                                    ownerVersion = optiondata[0];
                                    ownerSequence = optiondata[1];
                                    ownerPrimaryMacAddress = new byte[] { optiondata[2], optiondata[3], optiondata[4], optiondata[5], optiondata[6], optiondata[7] };
                                    ownerWakeupMacAddress = ownerPrimaryMacAddress;
                                    if (optiondata.length > 8) {
                                        // We have a wakeupMacAddress.
                                        ownerWakeupMacAddress = new byte[] { optiondata[8], optiondata[9], optiondata[10], optiondata[11], optiondata[12], optiondata[13] };
                                    }
                                    if (optiondata.length == 18) {
                                        // We have a short password.
                                        ownerPassword = new byte[] { optiondata[14], optiondata[15], optiondata[16], optiondata[17] };
                                    }
                                    if (optiondata.length == 22) {
                                        // We have a long password.
                                        ownerPassword = new byte[] { optiondata[14], optiondata[15], optiondata[16], optiondata[17], optiondata[18], optiondata[19], optiondata[20], optiondata[21] };
                                    }
                                } catch (Exception exception) {
                                    logger.warning("Malformed OPT answer. Option code: Owner data: " + this._hexString(optiondata));
                                }
                                if (logger.isLoggable(Level.FINE)) {
                                    logger.fine("Unhandled Owner OPT version: " + ownerVersion + " sequence: " + ownerSequence + " MAC address: " + this._hexString(ownerPrimaryMacAddress)
                                            + (ownerWakeupMacAddress != ownerPrimaryMacAddress ? " wakeup MAC address: " + this._hexString(ownerWakeupMacAddress) : "") + (ownerPassword != null ? " password: " + this._hexString(ownerPassword) : ""));
                                }
                                break;
                            case LLQ:
                            case NSID:
                            case UL:
                                if (logger.isLoggable(Level.FINE)) {
                                    logger.log(Level.FINE, "There was an OPT answer. Option code: " + optionCode + " data: " + this._hexString(optiondata));
                                }
                                break;
                            case Unknown:
                                logger.log(Level.WARNING, "There was an OPT answer. Not currently handled. Option code: " + optionCodeInt + " data: " + this._hexString(optiondata));
                                break;
                            default:
                                // This is to keep the compiler happy.
                                break;
                        }
                    }
                } else {
                    logger.log(Level.WARNING, "There was an OPT answer. Wrong version number: " + version + " result code: " + extendedResultCode);
                }
                break;
            default:
                if (logger.isLoggable(Level.FINER)) {
                    logger.finer("DNSIncoming() unknown type:" + type);
                }
                _messageInputStream.skip(len);
                break;
        }
        if (rec != null) {
            rec.setRecordSource(source);
        }
        return rec;
    }

    /**
     * Debugging.
     */
    String print(boolean dump) {
        StringBuilder buf = new StringBuilder();
        buf.append(this.print());
        if (dump) {
            byte[] data = new byte[_packet.getLength()];
            System.arraycopy(_packet.getData(), 0, data, 0, data.length);
            buf.append(this.print(data));
        }
        return buf.toString();
    }

    @Override
    public String toString() {
        StringBuilder buf = new StringBuilder();
        buf.append(isQuery() ? "dns[query," : "dns[response,");
        if (_packet.getAddress() != null) {
            buf.append(_packet.getAddress().getHostAddress());
        }
        buf.append(':');
        buf.append(_packet.getPort());
        buf.append(", length=");
        buf.append(_packet.getLength());
        buf.append(", id=0x");
        buf.append(Integer.toHexString(this.getId()));
        if (this.getFlags() != 0) {
            buf.append(", flags=0x");
            buf.append(Integer.toHexString(this.getFlags()));
            if ((this.getFlags() & DNSConstants.FLAGS_QR_RESPONSE) != 0) {
                buf.append(":r");
            }
            if ((this.getFlags() & DNSConstants.FLAGS_AA) != 0) {
                buf.append(":aa");
            }
            if ((this.getFlags() & DNSConstants.FLAGS_TC) != 0) {
                buf.append(":tc");
            }
        }
        if (this.getNumberOfQuestions() > 0) {
            buf.append(", questions=");
            buf.append(this.getNumberOfQuestions());
        }
        if (this.getNumberOfAnswers() > 0) {
            buf.append(", answers=");
            buf.append(this.getNumberOfAnswers());
        }
        if (this.getNumberOfAuthorities() > 0) {
            buf.append(", authorities=");
            buf.append(this.getNumberOfAuthorities());
        }
        if (this.getNumberOfAdditionals() > 0) {
            buf.append(", additionals=");
            buf.append(this.getNumberOfAdditionals());
        }
        if (this.getNumberOfQuestions() > 0) {
            buf.append("\nquestions:");
            for (DNSQuestion question : _questions) {
                buf.append("\n\t");
                buf.append(question);
            }
        }
        if (this.getNumberOfAnswers() > 0) {
            buf.append("\nanswers:");
            for (DNSRecord record : _answers) {
                buf.append("\n\t");
                buf.append(record);
            }
        }
        if (this.getNumberOfAuthorities() > 0) {
            buf.append("\nauthorities:");
            for (DNSRecord record : _authoritativeAnswers) {
                buf.append("\n\t");
                buf.append(record);
            }
        }
        if (this.getNumberOfAdditionals() > 0) {
            buf.append("\nadditionals:");
            for (DNSRecord record : _additionals) {
                buf.append("\n\t");
                buf.append(record);
            }
        }
        buf.append("]");
        return buf.toString();
    }

    /**
     * Appends answers to this Incoming.
     *
     * @exception IllegalArgumentException
     *                If not a query or if Truncated.
     */
    void append(DNSIncoming that) {
        if (this.isQuery() && this.isTruncated() && that.isQuery()) {
            this._questions.addAll(that.getQuestions());
            this._answers.addAll(that.getAnswers());
            this._authoritativeAnswers.addAll(that.getAuthorities());
            this._additionals.addAll(that.getAdditionals());
        } else {
            throw new IllegalArgumentException();
        }
    }

    public int elapseSinceArrival() {
        return (int) (System.currentTimeMillis() - _receivedTime);
    }

    /**
     * This will return the default UDP payload except if an OPT record was found with a different size.
     *
     * @return the senderUDPPayload
     */
    public int getSenderUDPPayload() {
        return this._senderUDPPayload;
    }

    private static final char[] _nibbleToHex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

    /**
     * Returns a hex-string for printing
     *
     * @param bytes
     * @return Returns a hex-string which can be used within a SQL expression
     */
    private String _hexString(byte[] bytes) {

        StringBuilder result = new StringBuilder(2 * bytes.length);

        for (int i = 0; i < bytes.length; i++) {
            int b = bytes[i] & 0xFF;
            result.append(_nibbleToHex[b / 16]);
            result.append(_nibbleToHex[b % 16]);
        }

        return result.toString();
    }

}
