001/*
002 * Copyright 2015-2024 the original author or authors
003 *
004 * This software is licensed under the Apache License, Version 2.0,
005 * the GNU Lesser General Public License version 2 or later ("LGPL")
006 * and the WTFPL.
007 * You may choose either license to govern your use of this software only
008 * upon the condition that you accept all of the terms of either
009 * the Apache License 2.0, the LGPL 2.1+ or the WTFPL.
010 */
011package org.minidns.edns;
012
013import java.io.DataOutputStream;
014import java.io.IOException;
015
016import org.minidns.edns.Edns.OptionCode;
017
018public abstract class EdnsOption {
019
020    public final int optionCode;
021    public final int optionLength;
022
023    protected final byte[] optionData;
024
025    protected EdnsOption(int optionCode, byte[] optionData) {
026        this.optionCode = optionCode;
027        this.optionLength = optionData.length;
028        this.optionData = optionData;
029    }
030
031    @SuppressWarnings("this-escape")
032    protected EdnsOption(byte[] optionData) {
033        this.optionCode = getOptionCode().asInt;
034        this.optionLength = optionData.length;
035        this.optionData =  optionData;
036    }
037
038    public final void writeToDos(DataOutputStream dos) throws IOException {
039        dos.writeShort(optionCode);
040        dos.writeShort(optionLength);
041        dos.write(optionData);
042    }
043
044    public abstract OptionCode getOptionCode();
045
046    private String toStringCache;
047
048    @Override
049    public final String toString() {
050        if (toStringCache == null) {
051            toStringCache = toStringInternal().toString();
052        }
053        return toStringCache;
054    }
055
056    protected abstract CharSequence toStringInternal();
057
058    private String terminalOutputCache;
059
060    public final String asTerminalOutput() {
061        if (terminalOutputCache == null) {
062            terminalOutputCache = asTerminalOutputInternal().toString();
063        }
064        return terminalOutputCache;
065    }
066
067    protected abstract CharSequence asTerminalOutputInternal();
068
069    public static EdnsOption parse(int intOptionCode, byte[] optionData) {
070        OptionCode optionCode = OptionCode.from(intOptionCode);
071        EdnsOption res;
072        switch (optionCode) {
073        case NSID:
074            res = new Nsid(optionData);
075            break;
076        default:
077            res = new UnknownEdnsOption(intOptionCode, optionData);
078            break;
079        }
080        return res;
081    }
082
083}