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.record;
012
013import org.minidns.edns.EdnsOption;
014import org.minidns.record.Record.TYPE;
015
016import java.io.DataInputStream;
017import java.io.DataOutputStream;
018import java.io.IOException;
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.List;
022
023/**
024 * OPT payload (see RFC 2671 for details).
025 */
026public class OPT extends Data {
027
028    public final List<EdnsOption> variablePart;
029
030    public OPT() {
031        this(Collections.<EdnsOption>emptyList());
032    }
033
034    public OPT(List<EdnsOption> variablePart) {
035        this.variablePart = Collections.unmodifiableList(variablePart);
036    }
037
038    public static OPT parse(DataInputStream dis, int payloadLength) throws IOException {
039        List<EdnsOption> variablePart;
040        if (payloadLength == 0) {
041            variablePart = Collections.emptyList();
042        } else {
043            int payloadLeft = payloadLength;
044            variablePart = new ArrayList<>(4);
045            while (payloadLeft > 0) {
046                int optionCode = dis.readUnsignedShort();
047                int optionLength = dis.readUnsignedShort();
048                byte[] optionData = new byte[optionLength];
049                dis.read(optionData);
050                EdnsOption ednsOption = EdnsOption.parse(optionCode, optionData);
051                variablePart.add(ednsOption);
052                payloadLeft -= 2 + 2 + optionLength;
053                // Assert that payloadLeft never becomes negative
054                assert payloadLeft >= 0;
055            }
056        }
057        return new OPT(variablePart);
058    }
059
060    @Override
061    public TYPE getType() {
062        return TYPE.OPT;
063    }
064
065    @Override
066    protected void serialize(DataOutputStream dos) throws IOException {
067        for (EdnsOption endsOption : variablePart) {
068            endsOption.writeToDos(dos);
069        }
070    }
071
072}