001/*
002 * Copyright 2015-2018 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.source;
012
013import org.minidns.DnsCache;
014import org.minidns.MiniDnsFuture;
015import org.minidns.MiniDnsFuture.InternalMiniDnsFuture;
016import org.minidns.dnsmessage.DnsMessage;
017
018import java.io.IOException;
019import java.net.InetAddress;
020
021public abstract class DnsDataSource {
022
023    public abstract DnsMessage query(DnsMessage message, InetAddress address, int port) throws IOException;
024
025    public MiniDnsFuture<DnsMessage, IOException> queryAsync(DnsMessage message, InetAddress address, int port, OnResponseCallback onResponseCallback) {
026        InternalMiniDnsFuture<DnsMessage, IOException> future = new InternalMiniDnsFuture<>();
027        DnsMessage result;
028        try {
029            result = query(message, address, port);
030        } catch (IOException e) {
031            future.setException(e);
032            return future;
033        }
034        future.setResult(result);
035        return future;
036    }
037
038    protected int udpPayloadSize = 1024;
039
040    /**
041     * DNS timeout.
042     */
043    protected int timeout = 5000;
044
045    /**
046     * Retrieve the current dns query timeout, in milliseconds.
047     *
048     * @return the current dns query timeout in milliseconds.
049     */
050    public int getTimeout() {
051        return timeout;
052    }
053
054    /**
055     * Change the dns query timeout for all future queries. The timeout
056     * must be specified in milliseconds.
057     *
058     * @param timeout new dns query timeout in milliseconds.
059     */
060    public void setTimeout(int timeout) {
061        if (timeout <= 0) {
062            throw new IllegalArgumentException("Timeout must be greater than zero");
063        }
064        this.timeout = timeout;
065    }
066
067    public int getUdpPayloadSize() {
068        return udpPayloadSize;
069    }
070
071    public void setUdpPayloadSize(int udpPayloadSize) {
072        if (udpPayloadSize <= 0) {
073            throw new IllegalArgumentException("UDP payload size must be greater than zero");
074        }
075        this.udpPayloadSize = udpPayloadSize;
076    }
077
078    private DnsCache cache;
079
080    protected final void cacheResult(DnsMessage request, DnsMessage response) {
081        final DnsCache activeCache = cache;
082        if (activeCache == null) {
083            return;
084        }
085        activeCache.put(request, response);
086    }
087
088    public enum QueryMode {
089        /**
090         * Perform the query mode that is assumed "best" for that particular case.
091         */
092        dontCare,
093
094        /**
095         * Try UDP first, and if the result is bigger than the maximum UDP payload size, or if something else goes wrong, fallback to TCP.
096         */
097        udpTcp,
098
099        /**
100         * Always use only TCP when querying DNS servers.
101         */
102        tcp,
103    }
104
105    private QueryMode queryMode = QueryMode.dontCare;
106
107    public void setQueryMode(QueryMode queryMode) {
108        if (queryMode == null) {
109            throw new IllegalArgumentException();
110        }
111        this.queryMode = queryMode;
112    }
113
114    public QueryMode getQueryMode() {
115        return queryMode;
116    }
117
118    public interface OnResponseCallback {
119        void onResponse(DnsMessage request, DnsMessage response);
120    }
121}