Cleaned up DnsClient
This commit is contained in:
parent
34f4ec836d
commit
c33a086465
|
@ -15,37 +15,39 @@
|
||||||
*/
|
*/
|
||||||
package dorkbox.network;
|
package dorkbox.network;
|
||||||
|
|
||||||
import static io.netty.resolver.dns.DnsServerAddressStreamProviders.platformDefault;
|
import static dorkbox.network.dns.resolver.addressProvider.DnsServerAddressStreamProviders.platformDefault;
|
||||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||||
import static io.netty.util.internal.ObjectUtil.intValue;
|
import static io.netty.util.internal.ObjectUtil.intValue;
|
||||||
|
|
||||||
import java.net.IDN;
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import dorkbox.network.connection.EndPoint;
|
import dorkbox.network.connection.EndPoint;
|
||||||
import dorkbox.network.dns.decoder.DomainDecoder;
|
import dorkbox.network.dns.DnsQuestion;
|
||||||
import dorkbox.network.dns.decoder.MailExchangerDecoder;
|
import dorkbox.network.dns.DnsResponse;
|
||||||
import dorkbox.network.dns.decoder.RecordDecoder;
|
import dorkbox.network.dns.constants.DnsRecordType;
|
||||||
import dorkbox.network.dns.decoder.ServiceDecoder;
|
import dorkbox.network.dns.constants.DnsResponseCode;
|
||||||
import dorkbox.network.dns.decoder.StartOfAuthorityDecoder;
|
import dorkbox.network.dns.constants.DnsSection;
|
||||||
import dorkbox.network.dns.decoder.TextDecoder;
|
import dorkbox.network.dns.records.DnsRecord;
|
||||||
import dorkbox.network.dns.record.MailExchangerRecord;
|
import dorkbox.network.dns.resolver.DnsNameResolver;
|
||||||
import dorkbox.network.dns.record.ServiceRecord;
|
import dorkbox.network.dns.resolver.DnsQueryLifecycleObserverFactory;
|
||||||
import dorkbox.network.dns.record.StartOfAuthorityRecord;
|
import dorkbox.network.dns.resolver.NoopDnsQueryLifecycleObserverFactory;
|
||||||
|
import dorkbox.network.dns.resolver.addressProvider.DefaultDnsServerAddressStreamProvider;
|
||||||
|
import dorkbox.network.dns.resolver.addressProvider.DnsServerAddressStreamProvider;
|
||||||
|
import dorkbox.network.dns.resolver.addressProvider.SequentialDnsServerAddressStreamProvider;
|
||||||
|
import dorkbox.network.dns.resolver.cache.DefaultDnsCache;
|
||||||
|
import dorkbox.network.dns.resolver.cache.DnsCache;
|
||||||
import dorkbox.util.NamedThreadFactory;
|
import dorkbox.util.NamedThreadFactory;
|
||||||
import dorkbox.util.OS;
|
import dorkbox.util.OS;
|
||||||
import dorkbox.util.Property;
|
import dorkbox.util.Property;
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import io.netty.channel.AddressedEnvelope;
|
import io.netty.channel.AddressedEnvelope;
|
||||||
import io.netty.channel.ChannelFactory;
|
import io.netty.channel.ChannelFactory;
|
||||||
import io.netty.channel.EventLoopGroup;
|
import io.netty.channel.EventLoopGroup;
|
||||||
|
@ -58,25 +60,8 @@ import io.netty.channel.socket.DatagramChannel;
|
||||||
import io.netty.channel.socket.InternetProtocolFamily;
|
import io.netty.channel.socket.InternetProtocolFamily;
|
||||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||||
import io.netty.channel.socket.oio.OioDatagramChannel;
|
import io.netty.channel.socket.oio.OioDatagramChannel;
|
||||||
import io.netty.handler.codec.dns.DefaultDnsQuestion;
|
|
||||||
import io.netty.handler.codec.dns.DnsPtrRecord;
|
|
||||||
import io.netty.handler.codec.dns.DnsRawRecord;
|
|
||||||
import io.netty.handler.codec.dns.DnsRecord;
|
|
||||||
import io.netty.handler.codec.dns.DnsRecordType;
|
|
||||||
import io.netty.handler.codec.dns.DnsResponse;
|
|
||||||
import io.netty.handler.codec.dns.DnsResponseCode;
|
|
||||||
import io.netty.handler.codec.dns.DnsSection;
|
|
||||||
import io.netty.resolver.HostsFileEntriesResolver;
|
import io.netty.resolver.HostsFileEntriesResolver;
|
||||||
import io.netty.resolver.ResolvedAddressTypes;
|
import io.netty.resolver.ResolvedAddressTypes;
|
||||||
import io.netty.resolver.dns.DefaultDnsCache;
|
|
||||||
import io.netty.resolver.dns.DefaultDnsServerAddressStreamProvider;
|
|
||||||
import io.netty.resolver.dns.DnsCache;
|
|
||||||
import io.netty.resolver.dns.DnsNameResolver;
|
|
||||||
import io.netty.resolver.dns.DnsNameResolverAccess;
|
|
||||||
import io.netty.resolver.dns.DnsQueryLifecycleObserverFactory;
|
|
||||||
import io.netty.resolver.dns.DnsServerAddressStreamProvider;
|
|
||||||
import io.netty.resolver.dns.NoopDnsQueryLifecycleObserverFactory;
|
|
||||||
import io.netty.resolver.dns.SequentialDnsServerAddressStreamProvider;
|
|
||||||
import io.netty.util.concurrent.Future;
|
import io.netty.util.concurrent.Future;
|
||||||
import io.netty.util.internal.PlatformDependent;
|
import io.netty.util.internal.PlatformDependent;
|
||||||
|
|
||||||
|
@ -87,6 +72,21 @@ import io.netty.util.internal.PlatformDependent;
|
||||||
public
|
public
|
||||||
class DnsClient extends EndPoint {
|
class DnsClient extends EndPoint {
|
||||||
|
|
||||||
|
/*
|
||||||
|
http://bugs.java.com/view_bug.do?bug_id=8176361
|
||||||
|
Previous JDK releases documented how to configure `java.net.InetAddress` to use the JNDI DNS service provider as the name service. This mechanism, and the system properties to configure it, have been removed in JDK 9
|
||||||
|
|
||||||
|
A new mechanism to configure the use of a hosts file has been introduced.
|
||||||
|
|
||||||
|
A new system property `jdk.net.hosts.file` has been defined. When this system property is set, the name and address resolution calls of `InetAddress`, i.e `getByXXX`, retrieve the relevant mapping from the specified file. The structure of this file is equivalent to that of the `/etc/hosts` file.
|
||||||
|
|
||||||
|
When the system property `jdk.net.hosts.file` is set, and the specified file doesn't exist, the name or address lookup will result in an UnknownHostException. Thus, a non existent hosts file is handled as if the file is empty.
|
||||||
|
|
||||||
|
|
||||||
|
UP UNTIL java 1.8, one can use org/xbill/DNS/spi, ie: sun.net.dns.ResolverConfiguration
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a list of all of the public DNS servers to query, when submitting DNS queries
|
* This is a list of all of the public DNS servers to query, when submitting DNS queries
|
||||||
*/
|
*/
|
||||||
|
@ -109,6 +109,7 @@ class DnsClient extends EndPoint {
|
||||||
public final static List<InetSocketAddress> DEFAULT_DNS_SERVER_LIST = DefaultDnsServerAddressStreamProvider.defaultAddressList();
|
public final static List<InetSocketAddress> DEFAULT_DNS_SERVER_LIST = DefaultDnsServerAddressStreamProvider.defaultAddressList();
|
||||||
|
|
||||||
private static final String ptrSuffix = ".in-addr.arpa";
|
private static final String ptrSuffix = ".in-addr.arpa";
|
||||||
|
public static final InetAddress[] INET_ADDRESSES = new InetAddress[0];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the version number.
|
* Gets the version number.
|
||||||
|
@ -128,22 +129,29 @@ class DnsClient extends EndPoint {
|
||||||
* @return the public IP address if found, or null if it didn't find it
|
* @return the public IP address if found, or null if it didn't find it
|
||||||
*/
|
*/
|
||||||
public static
|
public static
|
||||||
String getPublicIp() {
|
InetAddress getPublicIp() {
|
||||||
final InetSocketAddress dnsServer = new InetSocketAddress("208.67.222.222", 53); // openDNS
|
final InetSocketAddress dnsServer = new InetSocketAddress("208.67.222.222", 53); // openDNS
|
||||||
|
|
||||||
DnsClient dnsClient = new DnsClient(dnsServer);
|
DnsClient dnsClient = new DnsClient(dnsServer);
|
||||||
final String resolve = dnsClient.resolve("myip.opendns.com", DnsRecordType.A);
|
List<InetAddress> resolved = null;
|
||||||
|
try {
|
||||||
|
resolved = dnsClient.resolve("myip.opendns.com");
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
dnsClient.stop();
|
dnsClient.stop();
|
||||||
|
|
||||||
return resolve;
|
if (resolved != null && resolved.size() > 0) {
|
||||||
|
return resolved.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(getClass());
|
private final Logger logger = org.slf4j.LoggerFactory.getLogger(getClass());
|
||||||
private Class<? extends DatagramChannel> channelType;
|
private Class<? extends DatagramChannel> channelType;
|
||||||
|
|
||||||
private DnsNameResolver resolver;
|
private DnsNameResolver resolver;
|
||||||
private final Map<DnsRecordType, RecordDecoder<?>> customDecoders = new HashMap<DnsRecordType, RecordDecoder<?>>();
|
|
||||||
|
|
||||||
private ThreadGroup threadGroup;
|
private ThreadGroup threadGroup;
|
||||||
private static final String THREAD_NAME = "DnsClient";
|
private static final String THREAD_NAME = "DnsClient";
|
||||||
|
@ -160,15 +168,13 @@ class DnsClient extends EndPoint {
|
||||||
private Integer negativeTtl;
|
private Integer negativeTtl;
|
||||||
private long queryTimeoutMillis = 5000;
|
private long queryTimeoutMillis = 5000;
|
||||||
|
|
||||||
private ResolvedAddressTypes resolvedAddressTypes = DnsNameResolverAccess.getDefaultResolvedAddressTypes();
|
private ResolvedAddressTypes resolvedAddressTypes = DnsNameResolver.DEFAULT_RESOLVE_ADDRESS_TYPES;
|
||||||
private boolean recursionDesired = true;
|
private boolean recursionDesired = true;
|
||||||
private int maxQueriesPerResolve = 16;
|
private int maxQueriesPerResolve = 16;
|
||||||
|
|
||||||
private boolean traceEnabled;
|
private boolean traceEnabled;
|
||||||
private int maxPayloadSize = 4096;
|
private int maxPayloadSize = 4096;
|
||||||
|
|
||||||
private boolean optResourceEnabled = true;
|
|
||||||
|
|
||||||
private HostsFileEntriesResolver hostsFileEntriesResolver = HostsFileEntriesResolver.DEFAULT;
|
private HostsFileEntriesResolver hostsFileEntriesResolver = HostsFileEntriesResolver.DEFAULT;
|
||||||
private DnsServerAddressStreamProvider dnsServerAddressStreamProvider = platformDefault();
|
private DnsServerAddressStreamProvider dnsServerAddressStreamProvider = platformDefault();
|
||||||
private DnsQueryLifecycleObserverFactory dnsQueryLifecycleObserverFactory = NoopDnsQueryLifecycleObserverFactory.INSTANCE;
|
private DnsQueryLifecycleObserverFactory dnsQueryLifecycleObserverFactory = NoopDnsQueryLifecycleObserverFactory.INSTANCE;
|
||||||
|
@ -192,7 +198,17 @@ class DnsClient extends EndPoint {
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
DnsClient(final String nameServerAddresses) {
|
DnsClient(final String nameServerAddresses) {
|
||||||
this(Collections.singletonList(new InetSocketAddress(nameServerAddresses, 53)));
|
this(nameServerAddresses, 53);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new DNS client, using the provided server and por tfor DNS query resolution, with a cache that will obey the TTL of the response
|
||||||
|
*
|
||||||
|
* @param nameServerAddresses the server to receive your DNS questions.
|
||||||
|
*/
|
||||||
|
public
|
||||||
|
DnsClient(final String nameServerAddresses, int port) {
|
||||||
|
this(Collections.singletonList(new InetSocketAddress(nameServerAddresses, port)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -234,18 +250,6 @@ class DnsClient extends EndPoint {
|
||||||
|
|
||||||
manageForShutdown(eventLoopGroup);
|
manageForShutdown(eventLoopGroup);
|
||||||
|
|
||||||
// NOTE: A/AAAA use the built-in decoder
|
|
||||||
|
|
||||||
customDecoders.put(DnsRecordType.MX, new MailExchangerDecoder());
|
|
||||||
customDecoders.put(DnsRecordType.TXT, new TextDecoder());
|
|
||||||
customDecoders.put(DnsRecordType.SRV, new ServiceDecoder());
|
|
||||||
|
|
||||||
RecordDecoder<?> decoder = new DomainDecoder();
|
|
||||||
customDecoders.put(DnsRecordType.NS, decoder);
|
|
||||||
customDecoders.put(DnsRecordType.CNAME, decoder);
|
|
||||||
customDecoders.put(DnsRecordType.PTR, decoder);
|
|
||||||
customDecoders.put(DnsRecordType.SOA, new StartOfAuthorityDecoder());
|
|
||||||
|
|
||||||
if (nameServerAddresses != null) {
|
if (nameServerAddresses != null) {
|
||||||
this.dnsServerAddressStreamProvider = new SequentialDnsServerAddressStreamProvider(nameServerAddresses);
|
this.dnsServerAddressStreamProvider = new SequentialDnsServerAddressStreamProvider(nameServerAddresses);
|
||||||
}
|
}
|
||||||
|
@ -404,21 +408,6 @@ class DnsClient extends EndPoint {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable the automatic inclusion of a optional records that tries to give the remote DNS server a hint about
|
|
||||||
* how much data the resolver can read per response. Some DNSServer may not support this and so fail to answer
|
|
||||||
* queries. If you find problems you may want to disable this.
|
|
||||||
*
|
|
||||||
* @param optResourceEnabled if optional records inclusion is enabled
|
|
||||||
*
|
|
||||||
* @return {@code this}
|
|
||||||
*/
|
|
||||||
public
|
|
||||||
DnsClient optResourceEnabled(boolean optResourceEnabled) {
|
|
||||||
this.optResourceEnabled = optResourceEnabled;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param hostsFileEntriesResolver the {@link HostsFileEntriesResolver} used to first check
|
* @param hostsFileEntriesResolver the {@link HostsFileEntriesResolver} used to first check
|
||||||
* if the hostname is locally aliased.
|
* if the hostname is locally aliased.
|
||||||
|
@ -519,7 +508,7 @@ class DnsClient extends EndPoint {
|
||||||
public static
|
public static
|
||||||
ResolvedAddressTypes computeResolvedAddressTypes(InternetProtocolFamily... internetProtocolFamilies) {
|
ResolvedAddressTypes computeResolvedAddressTypes(InternetProtocolFamily... internetProtocolFamilies) {
|
||||||
if (internetProtocolFamilies == null || internetProtocolFamilies.length == 0) {
|
if (internetProtocolFamilies == null || internetProtocolFamilies.length == 0) {
|
||||||
return DnsNameResolverAccess.getDefaultResolvedAddressTypes();
|
return DnsNameResolver.DEFAULT_RESOLVE_ADDRESS_TYPES;
|
||||||
}
|
}
|
||||||
if (internetProtocolFamilies.length > 2) {
|
if (internetProtocolFamilies.length > 2) {
|
||||||
throw new IllegalArgumentException("No more than 2 InternetProtocolFamilies");
|
throw new IllegalArgumentException("No more than 2 InternetProtocolFamilies");
|
||||||
|
@ -563,10 +552,22 @@ class DnsClient extends EndPoint {
|
||||||
DnsCache resolveCache = this.resolveCache != null ? this.resolveCache : newCache();
|
DnsCache resolveCache = this.resolveCache != null ? this.resolveCache : newCache();
|
||||||
DnsCache authoritativeDnsServerCache = this.authoritativeDnsServerCache != null ? this.authoritativeDnsServerCache : newCache();
|
DnsCache authoritativeDnsServerCache = this.authoritativeDnsServerCache != null ? this.authoritativeDnsServerCache : newCache();
|
||||||
|
|
||||||
resolver = new DnsNameResolver(eventLoopGroup.next(), channelFactory, resolveCache, authoritativeDnsServerCache,
|
resolver = new DnsNameResolver(eventLoopGroup.next(),
|
||||||
dnsQueryLifecycleObserverFactory, queryTimeoutMillis, resolvedAddressTypes, recursionDesired,
|
channelFactory,
|
||||||
maxQueriesPerResolve, traceEnabled, maxPayloadSize, optResourceEnabled, hostsFileEntriesResolver,
|
resolveCache,
|
||||||
dnsServerAddressStreamProvider, searchDomains, ndots, decodeIdn);
|
authoritativeDnsServerCache,
|
||||||
|
dnsQueryLifecycleObserverFactory,
|
||||||
|
queryTimeoutMillis,
|
||||||
|
resolvedAddressTypes,
|
||||||
|
recursionDesired,
|
||||||
|
maxQueriesPerResolve,
|
||||||
|
traceEnabled,
|
||||||
|
maxPayloadSize,
|
||||||
|
hostsFileEntriesResolver,
|
||||||
|
dnsServerAddressStreamProvider,
|
||||||
|
searchDomains,
|
||||||
|
ndots,
|
||||||
|
decodeIdn);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -592,181 +593,116 @@ class DnsClient extends EndPoint {
|
||||||
@Override
|
@Override
|
||||||
protected
|
protected
|
||||||
void stopExtraActions() {
|
void stopExtraActions() {
|
||||||
clearResolver();
|
|
||||||
|
|
||||||
if (resolver != null) {
|
if (resolver != null) {
|
||||||
|
clearResolver();
|
||||||
|
|
||||||
resolver.close(); // also closes the UDP channel that DNS client uses
|
resolver.close(); // also closes the UDP channel that DNS client uses
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves a specific hostname A record
|
* Resolves a specific hostname A/AAAA record.
|
||||||
*
|
*
|
||||||
* @param hostname the hostname, ie: google.com, that you want to resolve
|
* @param hostname the hostname, ie: google.com, that you want to resolve
|
||||||
|
* @return the list of resolved InetAddress or null
|
||||||
|
* @throws UnknownHostException if the hostname cannot be resolved
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
String resolve(String hostname) {
|
List<InetAddress> resolve(String hostname) throws UnknownHostException {
|
||||||
if (resolver == null) {
|
if (resolver == null) {
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resolver.resolvedAddressTypes() == ResolvedAddressTypes.IPV4_ONLY) {
|
// use "resolve", since it handles A/AAAA records + redirects correctly
|
||||||
return resolve(hostname, DnsRecordType.A);
|
final Future<List<InetAddress>> resolve = resolver.resolveAll(hostname);
|
||||||
|
final Future<List<InetAddress>> result = resolve.awaitUninterruptibly();
|
||||||
|
|
||||||
|
// now return whatever value we had
|
||||||
|
if (result.isSuccess() && result.isDone()) {
|
||||||
|
try {
|
||||||
|
List<InetAddress> now = result.getNow();
|
||||||
|
return now;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Could not ask question to DNS server", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return resolve(hostname, DnsRecordType.AAAA);
|
logger.error("Could not ask question to DNS server for A/AAAA record: {}", hostname);
|
||||||
|
|
||||||
|
UnknownHostException cause = (UnknownHostException) result.cause();
|
||||||
|
if (cause != null) {
|
||||||
|
throw cause;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves a specific hostname record, of the specified type (PTR, MX, TXT, etc)
|
* Resolves a specific hostname record, of the specified type (PTR, MX, TXT, etc)
|
||||||
* <p/>
|
* <p/>
|
||||||
* Note that PTR absolutely MUST end in '.in-addr.arpa' in order for the DNS server to understand it.
|
* <p/>
|
||||||
|
* Note: PTR queries absolutely MUST end in '.in-addr.arpa' in order for the DNS server to understand it.
|
||||||
* -- because of this, we will automatically fix this in case that clients are unaware of this requirement
|
* -- because of this, we will automatically fix this in case that clients are unaware of this requirement
|
||||||
|
* <p/>
|
||||||
|
* <p/>
|
||||||
|
* Note: A/AAAA queries absolutely MUST end in a '.' -- because of this we will automatically fix this in case that clients are
|
||||||
|
* unaware of this requirement
|
||||||
*
|
*
|
||||||
* @param hostname the hostname, ie: google.com, that you want to resolve
|
* @param hostname the hostname, ie: google.com, that you want to resolve
|
||||||
* @param type the DnsRecordType you want to resolve (PTR, MX, TXT, etc)
|
* @param type the DnsRecordType you want to resolve (PTR, MX, TXT, etc)
|
||||||
* @return null indicates there was an error resolving the hostname
|
* @return the DnsRecords or null if there was an error resolving the hostname
|
||||||
|
*
|
||||||
|
* @throws @throws UnknownHostException if the hostname cannot be resolved
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings({"unchecked", "Duplicates"})
|
||||||
private
|
public
|
||||||
<T> T resolve(String hostname, DnsRecordType type) {
|
DnsRecord[] query(String hostname, final int type) throws UnknownHostException {
|
||||||
if (resolver == null) {
|
if (resolver == null) {
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
hostname = IDN.toASCII(hostname);
|
if (type == DnsRecordType.PTR && !hostname.endsWith(ptrSuffix)) {
|
||||||
final int value = type.intValue();
|
// PTR absolutely MUST end in '.in-addr.arpa' in order for the DNS server to understand it.
|
||||||
|
// in this case, hostname is an ip address
|
||||||
|
|
||||||
// we can use the included DNS resolver.
|
|
||||||
if (value == DnsRecordType.A.intValue() || value == DnsRecordType.AAAA.intValue()) {
|
|
||||||
// use "resolve", since it handles A/AAAA records
|
|
||||||
final Future<InetAddress> resolve = resolver.resolve(hostname); // made up port, because it doesn't matter
|
|
||||||
final Future<InetAddress> result = resolve.awaitUninterruptibly();
|
|
||||||
|
|
||||||
// now return whatever value we had
|
|
||||||
if (result.isSuccess() && result.isDone()) {
|
|
||||||
try {
|
|
||||||
return (T) result.getNow().getHostAddress();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("Could not ask question to DNS server", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Throwable cause = result.cause();
|
|
||||||
|
|
||||||
Logger logger2 = this.logger;
|
|
||||||
if (logger2.isDebugEnabled() && cause != null) {
|
|
||||||
logger2.error("Could not ask question to DNS server.", cause);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// we use our own resolvers
|
|
||||||
|
|
||||||
final Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> query = resolver.query(new DefaultDnsQuestion(hostname, type));
|
|
||||||
final Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> result = query.awaitUninterruptibly();
|
|
||||||
|
|
||||||
// now return whatever value we had
|
|
||||||
if (result.isSuccess() && result.isDone()) {
|
|
||||||
AddressedEnvelope<DnsResponse, InetSocketAddress> envelope = result.getNow();
|
|
||||||
DnsResponse response = envelope.content();
|
|
||||||
try {
|
|
||||||
final DnsResponseCode code = response.code();
|
|
||||||
if (code == DnsResponseCode.NOERROR) {
|
|
||||||
final RecordDecoder<?> decoder = customDecoders.get(type);
|
|
||||||
if (decoder != null) {
|
|
||||||
final int answerCount = response.count(DnsSection.ANSWER);
|
|
||||||
for (int i = 0; i < answerCount; i++) {
|
|
||||||
final DnsRecord r = response.recordAt(DnsSection.ANSWER, i);
|
|
||||||
if (r.type() == type) {
|
|
||||||
// can be either RAW or it will be a PTR record
|
|
||||||
if (r instanceof DnsRawRecord) {
|
|
||||||
ByteBuf recordContent = ((DnsRawRecord) r).content();
|
|
||||||
return (T) decoder.decode(r, recordContent);
|
|
||||||
} else if (r instanceof DnsPtrRecord) {
|
|
||||||
return (T) ((DnsPtrRecord)r).hostname();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.error("Could not ask question to DNS server: Issue with decoder for type: {}", type);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.error("Could not ask question to DNS server: Error code {}", code);
|
|
||||||
return null;
|
|
||||||
} finally {
|
|
||||||
response.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Throwable cause = result.cause();
|
|
||||||
|
|
||||||
Logger logger2 = this.logger;
|
|
||||||
if (logger2.isDebugEnabled() && cause != null) {
|
|
||||||
logger2.error("Could not ask question to DNS server.", cause);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.error("Could not ask question to DNS server for type: {}", type.getClass().getSimpleName());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public
|
|
||||||
ServiceRecord resolveSRV(final String hostname) {
|
|
||||||
return resolve(hostname, DnsRecordType.SRV);
|
|
||||||
}
|
|
||||||
|
|
||||||
public
|
|
||||||
MailExchangerRecord resolveMX(final String hostname) {
|
|
||||||
return resolve(hostname, DnsRecordType.MX);
|
|
||||||
}
|
|
||||||
|
|
||||||
public
|
|
||||||
String resolveCNAME(final String hostname) {
|
|
||||||
return resolve(hostname, DnsRecordType.CNAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
public
|
|
||||||
String resolveNS(final String hostname) {
|
|
||||||
return resolve(hostname, DnsRecordType.NS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public
|
|
||||||
String resolvePTR(String hostname) {
|
|
||||||
// PTR absolutely MUST end in ".in-addr.arpa"
|
|
||||||
if (!hostname.endsWith(ptrSuffix)) {
|
|
||||||
hostname += ptrSuffix;
|
hostname += ptrSuffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolve(hostname, DnsRecordType.PTR);
|
// we use our own resolvers
|
||||||
}
|
DnsQuestion dnsMessage = DnsQuestion.newQuery(hostname, type, recursionDesired);
|
||||||
|
|
||||||
public
|
final Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> query = resolver.query(dnsMessage);
|
||||||
String resolveA(final String hostname) {
|
final Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> result = query.awaitUninterruptibly();
|
||||||
return resolve(hostname, DnsRecordType.A);
|
|
||||||
}
|
|
||||||
|
|
||||||
public
|
// now return whatever value we had
|
||||||
String resolveAAAA(final String hostname) {
|
if (result.isSuccess() && result.isDone()) {
|
||||||
return resolve(hostname, DnsRecordType.AAAA);
|
AddressedEnvelope<DnsResponse, InetSocketAddress> envelope = result.getNow();
|
||||||
}
|
DnsResponse response = envelope.content();
|
||||||
|
try {
|
||||||
|
final int code = response.getHeader().getRcode();
|
||||||
|
if (code == DnsResponseCode.NOERROR) {
|
||||||
|
return response.getSectionArray(DnsSection.ANSWER);
|
||||||
|
}
|
||||||
|
|
||||||
public
|
logger.error("Could not ask question to DNS server: Error code {} for type: {} - {}",
|
||||||
StartOfAuthorityRecord resolveSOA(final String hostname) {
|
code, type, DnsRecordType.string(type));
|
||||||
return resolve(hostname, DnsRecordType.SOA);
|
|
||||||
}
|
|
||||||
|
|
||||||
public
|
logger.error("Could not ask question to DNS server: Error code {}", code);
|
||||||
List<String> resolveTXT(final String hostname) {
|
return null;
|
||||||
return resolve(hostname, DnsRecordType.TXT);
|
} finally {
|
||||||
|
response.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.error("Could not ask question to DNS server for type: {}", DnsRecordType.string(type));
|
||||||
|
|
||||||
|
UnknownHostException cause = (UnknownHostException) result.cause();
|
||||||
|
if (cause != null) {
|
||||||
|
throw cause;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user