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 java.io.DataInputStream;
014import java.io.DataOutputStream;
015import java.io.IOException;
016
017import org.minidns.dnsname.DnsName;
018import org.minidns.record.Record.TYPE;
019
020/**
021 * SRV record payload (service pointer).
022 */
023public class SRV extends RRWithTarget implements Comparable<SRV> {
024
025    /**
026     * The priority of this service. Lower values mean higher priority.
027     */
028    public final int priority;
029
030    /**
031     * The weight of this service. Services with the same priority should be
032     * balanced based on weight.
033     */
034    public final int weight;
035
036    /**
037     * The target port.
038     */
039    public final int port;
040
041    public static SRV parse(DataInputStream dis, byte[] data)
042        throws IOException {
043        int priority = dis.readUnsignedShort();
044        int weight = dis.readUnsignedShort();
045        int port = dis.readUnsignedShort();
046        DnsName target = DnsName.parse(dis, data);
047        return new SRV(priority, weight, port, target);
048    }
049
050    public SRV(int priority, int weight, int port, String target) {
051        this(priority, weight, port, DnsName.from(target));
052    }
053
054    public SRV(int priority, int weight, int port, DnsName target) {
055        super(target);
056        this.priority = priority;
057        this.weight = weight;
058        this.port = port;
059    }
060
061    /**
062     * Check if the service is available at this domain. This checks f the target points to the root label. As per RFC
063     * 2782 the service is decidedly not available if there is only a single SRV answer pointing to the root label. From
064     * RFC 2782:
065     *
066     * <blockquote>A Target of "." means that the service is decidedly not available at this domain.</blockquote>
067     *
068     * @return true if the service is available at this domain.
069     */
070    public boolean isServiceAvailable() {
071        return !target.isRootLabel();
072    }
073
074    @Override
075    public void serialize(DataOutputStream dos) throws IOException {
076        dos.writeShort(priority);
077        dos.writeShort(weight);
078        dos.writeShort(port);
079        super.serialize(dos);
080    }
081
082    @Override
083    public String toString() {
084        return priority + " " + weight + " " + port + " " + target + ".";
085    }
086
087    @Override
088    public TYPE getType() {
089        return TYPE.SRV;
090    }
091
092    @Override
093    public int compareTo(SRV other) {
094        int res = other.priority - this.priority;
095        if (res == 0) {
096            res = this.weight - other.weight;
097        }
098        return res;
099    }
100}