/*
* Copyright (c) 2011-2013 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.vertx.core.dns;
import io.vertx.codegen.annotations.DataObject;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.impl.AddressResolver;
import io.vertx.core.json.JsonObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Configuration options for Vert.x hostname resolver. The resolver uses the local <i>hosts</i> file and performs
* DNS <i>A</i> and <i>AAAA</i> queries.
*
* @author <a href="mailto:julien@julienviet.com">Julien Viet</a>
*/
@DataObject(generateConverter = true)
public class AddressResolverOptions {
/**
* The default list of DNS servers = null (uses system name server's list like resolve.conf otherwise Google Public DNS)
*/
public static final List<String> DEFAULT_SERVERS = null;
/**
* The default value for {@link #setOptResourceEnabled} = true
*/
public static final boolean DEFAULT_OPT_RESOURCE_ENABLED = true;
/**
* The default value for the negative cache min TTL = 0
*/
public static final int DEFAULT_CACHE_MIN_TIME_TO_LIVE = 0;
/**
* The default value for the negative cache max TTL = 0x7fffffff
*/
public static final int DEFAULT_CACHE_MAX_TIME_TO_LIVE = Integer.MAX_VALUE;
/**
* The default value for the negative cache TTL = 0
*/
public static final int DEFAULT_CACHE_NEGATIVE_TIME_TO_LIVE = 0;
/**
* The default value for the query timeout in millis = 5000
*/
public static final int DEFAULT_QUERY_TIMEOUT = 5000;
/**
* The default value for the max dns queries per query = 4
*/
public static final int DEFAULT_MAX_QUERIES = 4;
/**
* The default value of the rd flag = true
*/
public static final boolean DEFAULT_RD_FLAG = true;
/**
* The default value of search domains = null
*/
public static final List<String> DEFAULT_SEACH_DOMAINS = null;
/**
* The default ndots value = loads the value from the OS on Linux otherwise use the value 1
*/
public static final int DEFAULT_NDOTS = AddressResolver.DEFAULT_NDOTS_RESOLV_OPTION;
/**
* The default servers rotate value = loads the value from the OS on Linux otherwise use the value false
*/
public static final boolean DEFAULT_ROTATE_SERVERS = AddressResolver.DEFAULT_ROTATE_RESOLV_OPTION;
private String hostsPath;
private Buffer hostsValue;
private List<String> servers;
private boolean optResourceEnabled;
private int cacheMinTimeToLive;
private int cacheMaxTimeToLive;
private int cacheNegativeTimeToLive;
private long queryTimeout;
private int maxQueries;
private boolean rdFlag;
private List<String> searchDomains;
private int ndots;
private boolean rotateServers;
public AddressResolverOptions() {
servers = DEFAULT_SERVERS;
optResourceEnabled = DEFAULT_OPT_RESOURCE_ENABLED;
cacheMinTimeToLive = DEFAULT_CACHE_MIN_TIME_TO_LIVE;
cacheMaxTimeToLive = DEFAULT_CACHE_MAX_TIME_TO_LIVE;
cacheNegativeTimeToLive = DEFAULT_CACHE_NEGATIVE_TIME_TO_LIVE;
queryTimeout = DEFAULT_QUERY_TIMEOUT;
maxQueries = DEFAULT_MAX_QUERIES;
rdFlag = DEFAULT_RD_FLAG;
searchDomains = DEFAULT_SEACH_DOMAINS;
ndots = DEFAULT_NDOTS;
rotateServers = DEFAULT_ROTATE_SERVERS;
}
public AddressResolverOptions(AddressResolverOptions other) {
this.hostsPath = other.hostsPath;
this.hostsValue = other.hostsValue != null ? other.hostsValue.copy() : null;
this.servers = other.servers != null ? new ArrayList<>(other.servers) : null;
this.optResourceEnabled = other.optResourceEnabled;
this.cacheMinTimeToLive = other.cacheMinTimeToLive;
this.cacheMaxTimeToLive = other.cacheMaxTimeToLive;
this.cacheNegativeTimeToLive = other.cacheNegativeTimeToLive;
this.queryTimeout = other.queryTimeout;
this.maxQueries = other.maxQueries;
this.rdFlag = other.rdFlag;
this.searchDomains = other.searchDomains != null ? new ArrayList<>(other.searchDomains) : null;
this.ndots = other.ndots;
this.rotateServers = other.rotateServers;
}
public AddressResolverOptions(JsonObject json) {
this();
AddressResolverOptionsConverter.fromJson(json, this);
}
/**
* @return the path to the alternate hosts configuration file
*/
public String getHostsPath() {
return hostsPath;
}
/**
* Set the path of an alternate hosts configuration file to use instead of the one provided by the os.
* <p/>
* The default value is null, so the operating system hosts config is used.
*
* @param hostsPath the hosts path
* @return a reference to this, so the API can be used fluently
*/
public AddressResolverOptions setHostsPath(String hostsPath) {
this.hostsPath = hostsPath;
return this;
}
/**
* @return the hosts configuration file value
*/
public Buffer getHostsValue() {
return hostsValue;
}
/**
* Set an alternate hosts configuration file to use instead of the one provided by the os.
* <p/>
* The value should contain the hosts content literaly, for instance <i>127.0.0.1 localhost</i>
* <p/>
* The default value is null, so the operating system hosts config is used.
*
* @param hostsValue the hosts content
* @return a reference to this, so the API can be used fluently
*/
public AddressResolverOptions setHostsValue(Buffer hostsValue) {
this.hostsValue = hostsValue;
return this;
}
/**
* @return the list of dns server
*/
public List<String> getServers() {
return servers;
}
/**
* Set the list of DNS server addresses, an address is the IP of the dns server, followed by an optional
* colon and a port, e.g {@code 8.8.8.8} or {code 192.168.0.1:40000}. When the list is empty, the resolver
* will use the list of the system DNS server addresses from the environment, if that list cannot be retrieved
* it will use Google's public DNS servers {@code "8.8.8.8"} and {@code "8.8.4.4"}.
*
* @param servers the list of DNS servers
* @return a reference to this, so the API can be used fluently
*/
public AddressResolverOptions setServers(List<String> servers) {
this.servers = servers;
return this;
}
/**
* Add a DNS server address.
*
* @param server the server to add
* @return a reference to this, so the API can be used fluently
*/
public AddressResolverOptions addServer(String server) {
if (servers == null) {
servers = new ArrayList<>();
}
servers.add(server);
return this;
}
/**
* @return true if an optional record is automatically included in DNS queries
*/
public boolean isOptResourceEnabled() {
return optResourceEnabled;
}
/**
* Set to true to enable the automatic inclusion in DNS queries of an optional record that hints
* the remote DNS server about how much data the resolver can read per response.
*
* @param optResourceEnabled true to enable, false otherwise
* @return a reference to this, so the API can be used fluently
*/
public AddressResolverOptions setOptResourceEnabled(boolean optResourceEnabled) {
this.optResourceEnabled = optResourceEnabled;
return this;
}
/**
* @return the cache min TTL in seconds
*/
public int getCacheMinTimeToLive() {
return cacheMinTimeToLive;
}
/**
* Set the cache minimum TTL value in seconds. After resolution successful IP addresses are cached with their DNS response TTL,
* use this to set a minimum value to all responses TTL.
*
* @param cacheMinTimeToLive the cache min TTL in seconds
* @return a reference to this, so the API can be used fluently
*/
public AddressResolverOptions setCacheMinTimeToLive(int cacheMinTimeToLive) {
if (cacheMinTimeToLive < 0) {
throw new IllegalArgumentException("cacheMinTimeToLive must be >= 0");
}
this.cacheMinTimeToLive = cacheMinTimeToLive;
return this;
}
/**
* @return the cache max TTL in seconds
*/
public int getCacheMaxTimeToLive() {
return cacheMaxTimeToLive;
}
/**
* Set the cache maximum TTL value in seconds. After successful resolution IP addresses are cached with their DNS response TTL,
* use this to set a maximum value to all responses TTL.
*
* @param cacheMaxTimeToLive the cache max TTL in seconds
* @return a reference to this, so the API can be used fluently
*/
public AddressResolverOptions setCacheMaxTimeToLive(int cacheMaxTimeToLive) {
if (cacheMaxTimeToLive < 0) {
throw new IllegalArgumentException("cacheMaxTimeToLive must be >= 0");
}
this.cacheMaxTimeToLive = cacheMaxTimeToLive;
return this;
}
/**
* @return the cache negative TTL in seconds
*/
public int getCacheNegativeTimeToLive() {
return cacheNegativeTimeToLive;
}
/**
* Set the negative cache TTL value in seconds. After a failed hostname resolution, DNS queries won't be retried
* for a period of time equals to the negative TTL. This allows to reduce the response time of negative replies
* and reduce the amount of messages to DNS servers.
*
* @param cacheNegativeTimeToLive the cache negative TTL in seconds
* @return a reference to this, so the API can be used fluently
*/
public AddressResolverOptions setCacheNegativeTimeToLive(int cacheNegativeTimeToLive) {
if (cacheNegativeTimeToLive < 0) {
throw new IllegalArgumentException("cacheNegativeTimeToLive must be >= 0");
}
this.cacheNegativeTimeToLive = cacheNegativeTimeToLive;
return this;
}
/**
* @return the query timeout in milliseconds
*/
public long getQueryTimeout() {
return queryTimeout;
}
/**
* Set the query timeout in milliseconds, i.e the amount of time after a query is considered to be failed.
*
* @param queryTimeout the query timeout in milliseconds
* @return a reference to this, so the API can be used fluently
*/
public AddressResolverOptions setQueryTimeout(long queryTimeout) {
if (queryTimeout < 1) {
throw new IllegalArgumentException("queryTimeout must be > 0");
}
this.queryTimeout = queryTimeout;
return this;
}
/**
* @return the maximum number of queries to be sent during a resolution
*/
public int getMaxQueries() {
return maxQueries;
}
/**
* Set the maximum number of queries when an hostname is resolved.
*
* @param maxQueries the max number of queries to be sent
* @return a reference to this, so the API can be used fluently
*/
public AddressResolverOptions setMaxQueries(int maxQueries) {
if (maxQueries < 1) {
throw new IllegalArgumentException("maxQueries must be > 0");
}
this.maxQueries = maxQueries;
return this;
}
/**
* @return the DNS queries <i>Recursion Desired</i> flag value
*/
public boolean getRdFlag() {
return rdFlag;
}
/**
* Set the DNS queries <i>Recursion Desired</i> flag value.
*
* @param rdFlag the flag value
* @return a reference to this, so the API can be used fluently
*/
public AddressResolverOptions setRdFlag(boolean rdFlag) {
this.rdFlag = rdFlag;
return this;
}
/**
* @return the list of search domains
*/
public List<String> getSearchDomains() {
return searchDomains;
}
/**
* Set the lists of DNS search domains.
* <p/>
* When the search domain list is null, the effective search domain list will be populated using
* the system DNS search domains.
*
* @param searchDomains the search domains
*/
public AddressResolverOptions setSearchDomains(List<String> searchDomains) {
this.searchDomains = searchDomains;
return this;
}
/**
* Add a DNS search domain.
*
* @param searchDomain the search domain to add
* @return a reference to this, so the API can be used fluently
*/
public AddressResolverOptions addSearchDomain(String searchDomain) {
if (searchDomains == null) {
searchDomains = new ArrayList<>();
}
searchDomains.add(searchDomain);
return this;
}
/**
* @return the ndots value
*/
public int getNdots() {
return ndots;
}
/**
* Set the ndots value used when resolving using search domains, the default value is {@code -1} which
* determines the value from the OS on Linux or uses the value {@code 1}.
*
* @param ndots the new ndots value
* @return a reference to this, so the API can be used fluently
*/
public AddressResolverOptions setNdots(int ndots) {
if (ndots < -1) {
throw new IllegalArgumentException("ndots must be >= -1");
}
this.ndots = ndots;
return this;
}
/**
* @return the value {@code true} when the dns server selection uses round robin
*/
public boolean isRotateServers() {
return rotateServers;
}
/**
* Set to {@code true} to enable round-robin selection of the dns server to use. It spreads the query load
* among the servers and avoids all lookup to hit the first server of the list.
*
* @return a reference to this, so the API can be used fluently
*/
public AddressResolverOptions setRotateServers(boolean rotateServers) {
this.rotateServers = rotateServers;
return this;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AddressResolverOptions that = (AddressResolverOptions) o;
if (optResourceEnabled != that.optResourceEnabled) return false;
if (cacheMinTimeToLive != that.cacheMinTimeToLive) return false;
if (cacheMaxTimeToLive != that.cacheMaxTimeToLive) return false;
if (cacheNegativeTimeToLive != that.cacheNegativeTimeToLive) return false;
if (queryTimeout != that.queryTimeout) return false;
if (maxQueries != that.maxQueries) return false;
if (rdFlag != that.rdFlag) return false;
if (!Objects.equals(searchDomains, that.searchDomains)) return false;
if (ndots != that.ndots) return false;
if (servers != null ? !servers.equals(that.servers) : that.servers != null) return false;
return rotateServers == that.rotateServers;
}
@Override
public int hashCode() {
int result = optResourceEnabled ? 1 : 0;
result = 31 * result + (servers != null ? servers.hashCode() : 0);
result = 31 * result + cacheMinTimeToLive;
result = 31 * result + cacheMaxTimeToLive;
result = 31 * result + cacheNegativeTimeToLive;
result = 31 * result + Long.hashCode(queryTimeout);
result = 31 * result + maxQueries;
result = 31 * result + (searchDomains != null ? searchDomains.hashCode() : 0);
result = 31 * result + ndots;
result = 31 * result + Boolean.hashCode(rdFlag);
result = 31 * result + Boolean.hashCode(rotateServers);
return result;
}
public JsonObject toJson() {
JsonObject json = new JsonObject();
AddressResolverOptionsConverter.toJson(this, json);
return json;
}
}