Simplified resolver via DnsResponse->DnsEnvelope for all promise types
This commit is contained in:
parent
dc54c9b226
commit
12c7c9f0a5
109
src/dorkbox/network/dns/DnsEnvelope.java
Normal file
109
src/dorkbox/network/dns/DnsEnvelope.java
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright 2018 dorkbox, llc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package dorkbox.network.dns;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import dorkbox.network.dns.records.DnsMessage;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.AddressedEnvelope;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public
|
||||
class DnsEnvelope extends DnsMessage implements AddressedEnvelope<DnsEnvelope, InetSocketAddress> {
|
||||
|
||||
private InetSocketAddress localAddress;
|
||||
private InetSocketAddress remoteAddress;
|
||||
|
||||
public
|
||||
DnsEnvelope() {
|
||||
super();
|
||||
}
|
||||
|
||||
public
|
||||
DnsEnvelope(final ByteBuf buffer, final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws IOException {
|
||||
super(buffer);
|
||||
|
||||
this.localAddress = localAddress;
|
||||
this.remoteAddress = remoteAddress;
|
||||
}
|
||||
|
||||
|
||||
public
|
||||
DnsEnvelope(final DnsInput input, final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws IOException {
|
||||
super(input);
|
||||
|
||||
this.localAddress = localAddress;
|
||||
this.remoteAddress = remoteAddress;
|
||||
}
|
||||
|
||||
public
|
||||
void setLocalAddress(final InetSocketAddress localAddress) {
|
||||
this.localAddress = localAddress;
|
||||
}
|
||||
|
||||
public
|
||||
void setRemoteAddress(final InetSocketAddress remoteAddress) {
|
||||
this.remoteAddress = remoteAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsEnvelope content() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final
|
||||
InetSocketAddress sender() {
|
||||
return localAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final
|
||||
InetSocketAddress recipient() {
|
||||
return remoteAddress;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsEnvelope touch() {
|
||||
return (DnsEnvelope) super.touch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsEnvelope touch(Object hint) {
|
||||
return (DnsEnvelope) super.touch(hint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsEnvelope retain() {
|
||||
return (DnsEnvelope) super.retain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsEnvelope retain(int increment) {
|
||||
return (DnsEnvelope) super.retain(increment);
|
||||
}
|
||||
}
|
|
@ -6,12 +6,7 @@ import java.net.InetSocketAddress;
|
|||
import java.net.SocketAddress;
|
||||
import java.util.Locale;
|
||||
|
||||
import dorkbox.network.dns.constants.DnsClass;
|
||||
import dorkbox.network.dns.constants.DnsOpCode;
|
||||
import dorkbox.network.dns.constants.DnsRecordType;
|
||||
import dorkbox.network.dns.constants.DnsSection;
|
||||
import dorkbox.network.dns.constants.Flags;
|
||||
import dorkbox.network.dns.records.DnsMessage;
|
||||
import dorkbox.network.dns.constants.*;
|
||||
import dorkbox.network.dns.records.DnsRecord;
|
||||
import io.netty.channel.AddressedEnvelope;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
@ -20,29 +15,7 @@ import io.netty.util.internal.StringUtil;
|
|||
*
|
||||
*/
|
||||
public
|
||||
class DnsQuestion extends DnsMessage implements AddressedEnvelope<DnsQuestion, InetSocketAddress> {
|
||||
private InetSocketAddress recipient;
|
||||
private final boolean isResolveQuestion;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param isResolveQuestion true if it's a resolve question, which means we ALSO are going to keep resolving names until we get an IP
|
||||
* address.
|
||||
*/
|
||||
private
|
||||
DnsQuestion(final boolean isResolveQuestion) {
|
||||
this.isResolveQuestion = isResolveQuestion;
|
||||
this.recipient = null;
|
||||
}
|
||||
|
||||
public
|
||||
boolean isResolveQuestion() {
|
||||
return isResolveQuestion;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class DnsQuestion extends DnsEnvelope {
|
||||
public static
|
||||
DnsQuestion newResolveQuestion(final String inetHost, final int type, final boolean isRecursionDesired) {
|
||||
return newQuestion(inetHost, type, isRecursionDesired, true);
|
||||
|
@ -53,7 +26,6 @@ class DnsQuestion extends DnsMessage implements AddressedEnvelope<DnsQuestion, I
|
|||
return newQuestion(inetHost, type, isRecursionDesired, false);
|
||||
}
|
||||
|
||||
|
||||
private static
|
||||
DnsQuestion newQuestion(final String inetHost, final int type, final boolean isRecursionDesired, boolean isResolveQuestion) {
|
||||
|
||||
|
@ -63,6 +35,11 @@ class DnsQuestion extends DnsMessage implements AddressedEnvelope<DnsQuestion, I
|
|||
// - https://github.com/netty/netty/issues/4935
|
||||
String hostName = hostNameAsciiFix(checkNotNull(inetHost, "hostname"));
|
||||
|
||||
if (hostName == null) {
|
||||
// hostNameAsciiFix can throw a TextParseException if it fails to parse
|
||||
return null;
|
||||
}
|
||||
|
||||
hostName = hostName.toLowerCase(Locale.US);
|
||||
|
||||
|
||||
|
@ -103,7 +80,7 @@ class DnsQuestion extends DnsMessage implements AddressedEnvelope<DnsQuestion, I
|
|||
public static
|
||||
String hostNameAsciiFix(String inetHost) {
|
||||
try {
|
||||
String hostName = java.net.IDN.toASCII(inetHost);
|
||||
String hostName = java.net.IDN.toASCII(inetHost); // can throw IllegalArgumentException
|
||||
|
||||
// Check for http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6894622
|
||||
if (StringUtil.endsWith(inetHost, '.') && !StringUtil.endsWith(hostName, '.')) {
|
||||
|
@ -118,54 +95,46 @@ class DnsQuestion extends DnsMessage implements AddressedEnvelope<DnsQuestion, I
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private final boolean isResolveQuestion;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param isResolveQuestion true if it's a resolve question, which means we ALSO are going to keep resolving names until we get an IP
|
||||
* address.
|
||||
*/
|
||||
private
|
||||
DnsQuestion(final boolean isResolveQuestion) {
|
||||
super();
|
||||
|
||||
this.isResolveQuestion = isResolveQuestion;
|
||||
}
|
||||
|
||||
public
|
||||
boolean isResolveQuestion() {
|
||||
return isResolveQuestion;
|
||||
}
|
||||
|
||||
public
|
||||
void init(int id, InetSocketAddress recipient) {
|
||||
getHeader().setID(id);
|
||||
this.recipient = recipient;
|
||||
setRemoteAddress(recipient);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsQuestion content() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
InetSocketAddress sender() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
InetSocketAddress recipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsQuestion touch() {
|
||||
return (DnsQuestion) super.touch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsQuestion touch(Object hint) {
|
||||
return (DnsQuestion) super.touch(hint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsQuestion retain() {
|
||||
return (DnsQuestion) super.retain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsQuestion retain(int increment) {
|
||||
return (DnsQuestion) super.retain(increment);
|
||||
int hashCode() {
|
||||
int hashCode = super.hashCode();
|
||||
if (sender() != null) {
|
||||
hashCode = hashCode * 31 + sender().hashCode();
|
||||
}
|
||||
if (recipient() != null) {
|
||||
hashCode = hashCode * 31 + recipient().hashCode();
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -205,18 +174,5 @@ class DnsQuestion extends DnsMessage implements AddressedEnvelope<DnsQuestion, I
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
int hashCode() {
|
||||
int hashCode = super.hashCode();
|
||||
if (sender() != null) {
|
||||
hashCode = hashCode * 31 + sender().hashCode();
|
||||
}
|
||||
if (recipient() != null) {
|
||||
hashCode = hashCode * 31 + recipient().hashCode();
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ import java.io.IOException;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
|
||||
import dorkbox.network.dns.records.DnsMessage;
|
||||
import io.netty.channel.AddressedEnvelope;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
|
@ -27,74 +26,40 @@ import io.netty.util.internal.UnstableApi;
|
|||
* A {@link DnsResponse} implementation for UDP/IP.
|
||||
*/
|
||||
@UnstableApi
|
||||
public class DnsResponse extends DnsMessage implements AddressedEnvelope<DnsResponse, InetSocketAddress> {
|
||||
|
||||
private final InetSocketAddress sender;
|
||||
private final InetSocketAddress recipient;
|
||||
public
|
||||
class DnsResponse extends DnsEnvelope {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param sender the address of the sender
|
||||
* @param recipient the address of the recipient
|
||||
* @param localAddress the address of the sender
|
||||
* @param remoteAddress the address of the recipient
|
||||
*/
|
||||
public
|
||||
DnsResponse(InetSocketAddress sender, InetSocketAddress recipient, final DnsInput dnsInput) throws IOException {
|
||||
super(dnsInput);
|
||||
DnsResponse(final DnsInput dnsInput, InetSocketAddress localAddress, InetSocketAddress remoteAddress) throws IOException {
|
||||
super(dnsInput, localAddress, remoteAddress);
|
||||
|
||||
if (recipient == null && sender == null) {
|
||||
throw new NullPointerException("recipient and sender");
|
||||
if (remoteAddress == null && localAddress == null) {
|
||||
throw new NullPointerException("localAddress and remoteAddress");
|
||||
}
|
||||
|
||||
this.sender = sender;
|
||||
this.recipient = recipient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsResponse content() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress sender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress recipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsResponse touch() {
|
||||
return (DnsResponse) super.touch();
|
||||
int hashCode() {
|
||||
int hashCode = super.hashCode();
|
||||
if (sender() != null) {
|
||||
hashCode = hashCode * 31 + sender().hashCode();
|
||||
}
|
||||
if (recipient() != null) {
|
||||
hashCode = hashCode * 31 + recipient().hashCode();
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsResponse touch(Object hint) {
|
||||
return (DnsResponse) super.touch(hint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsResponse retain() {
|
||||
return (DnsResponse) super.retain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
DnsResponse retain(int increment) {
|
||||
return (DnsResponse) super.retain(increment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
@ -113,7 +78,8 @@ public class DnsResponse extends DnsMessage implements AddressedEnvelope<DnsResp
|
|||
if (that.sender() != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!sender().equals(that.sender())) {
|
||||
}
|
||||
else if (!sender().equals(that.sender())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -121,22 +87,11 @@ public class DnsResponse extends DnsMessage implements AddressedEnvelope<DnsResp
|
|||
if (that.recipient() != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!recipient().equals(that.recipient())) {
|
||||
}
|
||||
else if (!recipient().equals(that.recipient())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = super.hashCode();
|
||||
if (sender() != null) {
|
||||
hashCode = hashCode * 31 + sender().hashCode();
|
||||
}
|
||||
if (recipient() != null) {
|
||||
hashCode = hashCode * 31 + recipient().hashCode();
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,29 +28,16 @@ import java.util.List;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dorkbox.network.dns.DatagramDnsQueryEncoder;
|
||||
import dorkbox.network.dns.DatagramDnsResponseDecoder;
|
||||
import dorkbox.network.dns.DnsQuestion;
|
||||
import dorkbox.network.dns.DnsResponse;
|
||||
import dorkbox.network.dns.clientHandlers.DatagramDnsQueryEncoder;
|
||||
import dorkbox.network.dns.clientHandlers.DatagramDnsResponseDecoder;
|
||||
import dorkbox.network.dns.constants.DnsRecordType;
|
||||
import dorkbox.network.dns.resolver.addressProvider.DefaultDnsServerAddressStreamProvider;
|
||||
import dorkbox.network.dns.resolver.addressProvider.DnsServerAddressStream;
|
||||
import dorkbox.network.dns.resolver.addressProvider.DnsServerAddressStreamProvider;
|
||||
import dorkbox.network.dns.resolver.addressProvider.DnsServerAddresses;
|
||||
import dorkbox.network.dns.resolver.addressProvider.UnixResolverDnsServerAddressStreamProvider;
|
||||
import dorkbox.network.dns.resolver.addressProvider.*;
|
||||
import dorkbox.network.dns.resolver.cache.DnsCache;
|
||||
import dorkbox.network.dns.resolver.cache.DnsCacheEntry;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.AddressedEnvelope;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFactory;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.EventLoop;
|
||||
import io.netty.channel.FixedRecvByteBufAllocator;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.socket.DatagramChannel;
|
||||
import io.netty.channel.socket.InternetProtocolFamily;
|
||||
import io.netty.resolver.HostsFileEntriesResolver;
|
||||
|
@ -750,7 +737,7 @@ class DnsNameResolver extends InetNameResolver {
|
|||
* Sends a DNS query with the specified question.
|
||||
*/
|
||||
public
|
||||
Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> query(DnsQuestion question) {
|
||||
Future<DnsResponse> query(DnsQuestion question) {
|
||||
return query(nextNameServerAddress(), question);
|
||||
}
|
||||
|
||||
|
@ -764,48 +751,39 @@ class DnsNameResolver extends InetNameResolver {
|
|||
* Sends a DNS query with the specified question using the specified name server list.
|
||||
*/
|
||||
public
|
||||
Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> query(InetSocketAddress nameServerAddr, DnsQuestion question) {
|
||||
Future<DnsResponse> query(InetSocketAddress nameServerAddr, DnsQuestion question) {
|
||||
return query0(nameServerAddr,
|
||||
question,
|
||||
ch.eventLoop().<AddressedEnvelope<DnsResponse, InetSocketAddress>>newPromise());
|
||||
ch.eventLoop().<DnsResponse>newPromise());
|
||||
}
|
||||
|
||||
final
|
||||
Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> query0(InetSocketAddress nameServerAddr,
|
||||
Future<DnsResponse> query0(InetSocketAddress nameServerAddr,
|
||||
DnsQuestion question,
|
||||
Promise<AddressedEnvelope<DnsResponse, InetSocketAddress>> promise) {
|
||||
Promise<DnsResponse> promise) {
|
||||
return query0(nameServerAddr, question, ch.newPromise(), promise);
|
||||
}
|
||||
|
||||
final
|
||||
Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> query0(InetSocketAddress nameServerAddr,
|
||||
DnsQuestion question,
|
||||
ChannelPromise writePromise,
|
||||
Promise<AddressedEnvelope<DnsResponse, InetSocketAddress>> promise) {
|
||||
Future<DnsResponse> query0(InetSocketAddress nameServerAddr,
|
||||
DnsQuestion question,
|
||||
ChannelPromise writePromise,
|
||||
Promise<DnsResponse> promise) {
|
||||
assert !writePromise.isVoid();
|
||||
|
||||
final Promise<AddressedEnvelope<DnsResponse, InetSocketAddress>> castPromise = cast(checkNotNull(promise, "promise"));
|
||||
try {
|
||||
new DnsQueryContext(this, nameServerAddr, question, castPromise).query(writePromise);
|
||||
return castPromise;
|
||||
new DnsQueryContext(this, nameServerAddr, question, promise).query(writePromise);
|
||||
return promise;
|
||||
} catch (Exception e) {
|
||||
return castPromise.setFailure(e);
|
||||
return promise.setFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static
|
||||
Promise<AddressedEnvelope<DnsResponse, InetSocketAddress>> cast(Promise<?> promise) {
|
||||
return (Promise<AddressedEnvelope<DnsResponse, InetSocketAddress>>) promise;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends a DNS query with the specified question.
|
||||
*/
|
||||
public
|
||||
Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> query(DnsQuestion question,
|
||||
Promise<AddressedEnvelope<DnsResponse, InetSocketAddress>> promise) {
|
||||
Future<DnsResponse> query(DnsQuestion question, Promise<DnsResponse> promise) {
|
||||
return query(nextNameServerAddress(), question, promise);
|
||||
}
|
||||
|
||||
|
@ -813,10 +791,7 @@ class DnsNameResolver extends InetNameResolver {
|
|||
* Sends a DNS query with the specified question using the specified name server list.
|
||||
*/
|
||||
public
|
||||
Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> query(InetSocketAddress nameServerAddr,
|
||||
DnsQuestion question,
|
||||
Promise<AddressedEnvelope<DnsResponse, InetSocketAddress>> promise) {
|
||||
|
||||
Future<DnsResponse> query(InetSocketAddress nameServerAddr, DnsQuestion question, Promise<DnsResponse> promise) {
|
||||
return query0(nameServerAddr, question, null, promise);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,32 +22,18 @@ import static java.util.Collections.unmodifiableList;
|
|||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import dorkbox.network.dns.DnsQuestion;
|
||||
import dorkbox.network.dns.DnsResponse;
|
||||
import dorkbox.network.dns.constants.DnsRecordType;
|
||||
import dorkbox.network.dns.constants.DnsResponseCode;
|
||||
import dorkbox.network.dns.constants.DnsSection;
|
||||
import dorkbox.network.dns.records.AAAARecord;
|
||||
import dorkbox.network.dns.records.ARecord;
|
||||
import dorkbox.network.dns.records.CNAMERecord;
|
||||
import dorkbox.network.dns.records.DnsMessage;
|
||||
import dorkbox.network.dns.records.DnsRecord;
|
||||
import dorkbox.network.dns.records.NSRecord;
|
||||
import dorkbox.network.dns.records.*;
|
||||
import dorkbox.network.dns.resolver.addressProvider.DnsServerAddressStream;
|
||||
import dorkbox.network.dns.resolver.addressProvider.DnsServerAddresses;
|
||||
import dorkbox.network.dns.resolver.cache.DnsCache;
|
||||
import dorkbox.network.dns.resolver.cache.DnsCacheEntry;
|
||||
import io.netty.channel.AddressedEnvelope;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.socket.InternetProtocolFamily;
|
||||
import io.netty.util.concurrent.Future;
|
||||
|
@ -61,10 +47,10 @@ import io.netty.util.internal.ThrowableUtil;
|
|||
abstract
|
||||
class DnsNameResolverContext<T> {
|
||||
|
||||
private static final FutureListener<AddressedEnvelope<DnsResponse, InetSocketAddress>> RELEASE_RESPONSE = new FutureListener<AddressedEnvelope<DnsResponse, InetSocketAddress>>() {
|
||||
private static final FutureListener<DnsResponse> RELEASE_RESPONSE = new FutureListener<DnsResponse>() {
|
||||
@Override
|
||||
public
|
||||
void operationComplete(Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> future) {
|
||||
void operationComplete(Future<DnsResponse> future) {
|
||||
if (future.isSuccess()) {
|
||||
future.getNow()
|
||||
.release();
|
||||
|
@ -104,7 +90,7 @@ class DnsNameResolverContext<T> {
|
|||
private final int maxAllowedQueries;
|
||||
private final InternetProtocolFamily[] resolvedInternetProtocolFamilies;
|
||||
|
||||
private final Set<Future<AddressedEnvelope<DnsResponse, InetSocketAddress>>> queriesInProgress = Collections.newSetFromMap(new IdentityHashMap<Future<AddressedEnvelope<DnsResponse, InetSocketAddress>>, Boolean>());
|
||||
private final Set<Future<DnsResponse>> queriesInProgress = Collections.newSetFromMap(new IdentityHashMap<Future<DnsResponse>, Boolean>());
|
||||
|
||||
private List<DnsCacheEntry> resolvedEntries;
|
||||
private int allowedQueries;
|
||||
|
@ -323,20 +309,20 @@ class DnsNameResolverContext<T> {
|
|||
|
||||
final InetSocketAddress nameServerAddr = nameServerAddrStream.next();
|
||||
final ChannelPromise writePromise = parent.ch.newPromise();
|
||||
final Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> f =
|
||||
final Future<DnsResponse> f =
|
||||
parent.query0(nameServerAddr,
|
||||
question,
|
||||
writePromise,
|
||||
parent.ch.eventLoop().<AddressedEnvelope<DnsResponse, InetSocketAddress>>newPromise());
|
||||
parent.ch.eventLoop().<DnsResponse>newPromise());
|
||||
|
||||
queriesInProgress.add(f);
|
||||
|
||||
queryLifecycleObserver.queryWritten(nameServerAddr, writePromise);
|
||||
|
||||
f.addListener(new FutureListener<AddressedEnvelope<DnsResponse, InetSocketAddress>>() {
|
||||
f.addListener(new FutureListener<DnsResponse>() {
|
||||
@Override
|
||||
public
|
||||
void operationComplete(Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> future) {
|
||||
void operationComplete(Future<DnsResponse> future) {
|
||||
// future.result() should have refCnt=2
|
||||
// question should have refCnt=1
|
||||
queriesInProgress.remove(future);
|
||||
|
@ -346,7 +332,7 @@ class DnsNameResolverContext<T> {
|
|||
return;
|
||||
}
|
||||
|
||||
AddressedEnvelope<DnsResponse, InetSocketAddress> envelope = future.getNow();
|
||||
DnsResponse envelope = future.getNow();
|
||||
try {
|
||||
if (future.isSuccess()) {
|
||||
onResponse(nameServerAddrStream,
|
||||
|
@ -378,17 +364,15 @@ class DnsNameResolverContext<T> {
|
|||
|
||||
void onResponse(final DnsServerAddressStream nameServerAddrStream,
|
||||
final int nameServerAddrStreamIndex,
|
||||
final DnsQuestion question,
|
||||
AddressedEnvelope<DnsResponse, InetSocketAddress> envelope,
|
||||
final DnsQuestion question, DnsResponse response,
|
||||
final DnsQueryLifecycleObserver queryLifecycleObserver,
|
||||
Promise<T> promise) {
|
||||
|
||||
final DnsResponse res = envelope.content();
|
||||
final int code = res.getHeader()
|
||||
.getRcode();
|
||||
final int code = response.getHeader()
|
||||
.getRcode();
|
||||
|
||||
if (code == DnsResponseCode.NOERROR) {
|
||||
if (handleRedirect(question, envelope, queryLifecycleObserver, promise)) {
|
||||
if (handleRedirect(question, response, queryLifecycleObserver, promise)) {
|
||||
// Was a redirect so return here as everything else is handled in handleRedirect(...)
|
||||
return;
|
||||
}
|
||||
|
@ -396,10 +380,10 @@ class DnsNameResolverContext<T> {
|
|||
.getType();
|
||||
|
||||
if (type == DnsRecordType.A || type == DnsRecordType.AAAA) {
|
||||
onResponseAorAAAA(type, question, envelope, queryLifecycleObserver, promise);
|
||||
onResponseAorAAAA(type, question, response, queryLifecycleObserver, promise);
|
||||
}
|
||||
else if (type == DnsRecordType.CNAME) {
|
||||
onResponseCNAME(question, envelope, queryLifecycleObserver, promise);
|
||||
onResponseCNAME(question, response, queryLifecycleObserver, promise);
|
||||
}
|
||||
else {
|
||||
queryLifecycleObserver.queryFailed(UNRECOGNIZED_TYPE_QUERY_FAILED_EXCEPTION);
|
||||
|
@ -424,23 +408,20 @@ class DnsNameResolverContext<T> {
|
|||
* Handles a redirect answer if needed and returns {@code true} if a redirect query has been made.
|
||||
*/
|
||||
private
|
||||
boolean handleRedirect(DnsQuestion question,
|
||||
AddressedEnvelope<DnsResponse, InetSocketAddress> envelope,
|
||||
boolean handleRedirect(DnsQuestion question, DnsResponse response,
|
||||
final DnsQueryLifecycleObserver queryLifecycleObserver,
|
||||
Promise<T> promise) {
|
||||
|
||||
final DnsResponse res = envelope.content();
|
||||
|
||||
// Check if we have answers, if not this may be an non authority NS and so redirects must be handled.
|
||||
DnsRecord[] answerArray = res.getSectionArray(DnsSection.ANSWER);
|
||||
DnsRecord[] answerArray = response.getSectionArray(DnsSection.ANSWER);
|
||||
if (answerArray.length == 0) {
|
||||
AuthoritativeNameServerList serverNames = extractAuthoritativeNameServers(question.getQuestion()
|
||||
.getName()
|
||||
.toString(), res);
|
||||
.toString(), response);
|
||||
|
||||
if (serverNames != null) {
|
||||
List<InetSocketAddress> nameServers = new ArrayList<InetSocketAddress>(serverNames.size());
|
||||
DnsRecord[] additionalArray = res.getSectionArray(DnsSection.ADDITIONAL);
|
||||
DnsRecord[] additionalArray = response.getSectionArray(DnsSection.ADDITIONAL);
|
||||
|
||||
for (int i = 0; i < additionalArray.length; i++) {
|
||||
final DnsRecord r = additionalArray[i];
|
||||
|
@ -505,13 +486,11 @@ class DnsNameResolverContext<T> {
|
|||
|
||||
private
|
||||
void onResponseAorAAAA(int qType,
|
||||
DnsMessage question,
|
||||
AddressedEnvelope<DnsResponse, InetSocketAddress> envelope,
|
||||
DnsMessage question, DnsResponse response,
|
||||
final DnsQueryLifecycleObserver queryLifecycleObserver,
|
||||
Promise<T> promise) {
|
||||
|
||||
// We often get a bunch of CNAMES as well when we asked for A/AAAA.
|
||||
final DnsResponse response = envelope.content();
|
||||
final Map<String, String> cnames = buildAliasMap(response);
|
||||
|
||||
DnsRecord[] answerArray = response.getSectionArray(DnsSection.ANSWER);
|
||||
|
@ -573,7 +552,7 @@ class DnsNameResolverContext<T> {
|
|||
}
|
||||
else {
|
||||
// We asked for A/AAAA but we got only CNAME.
|
||||
onResponseCNAME(question, envelope, cnames, queryLifecycleObserver, promise);
|
||||
onResponseCNAME(question, response, cnames, queryLifecycleObserver, promise);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -595,16 +574,14 @@ class DnsNameResolverContext<T> {
|
|||
}
|
||||
|
||||
private
|
||||
void onResponseCNAME(DnsMessage question,
|
||||
AddressedEnvelope<DnsResponse, InetSocketAddress> envelope,
|
||||
void onResponseCNAME(DnsMessage question, DnsResponse response,
|
||||
final DnsQueryLifecycleObserver queryLifecycleObserver,
|
||||
Promise<T> promise) {
|
||||
onResponseCNAME(question, envelope, buildAliasMap(envelope.content()), queryLifecycleObserver, promise);
|
||||
onResponseCNAME(question, response, buildAliasMap(response), queryLifecycleObserver, promise);
|
||||
}
|
||||
|
||||
private
|
||||
void onResponseCNAME(DnsMessage question,
|
||||
AddressedEnvelope<DnsResponse, InetSocketAddress> response,
|
||||
void onResponseCNAME(DnsMessage question, DnsResponse response,
|
||||
Map<String, String> cnames,
|
||||
final DnsQueryLifecycleObserver queryLifecycleObserver,
|
||||
Promise<T> promise) {
|
||||
|
@ -748,8 +725,8 @@ class DnsNameResolverContext<T> {
|
|||
|
||||
if (!queriesInProgress.isEmpty()) {
|
||||
// If there are queries in progress, we should cancel it because we already finished the resolution.
|
||||
for (Iterator<Future<AddressedEnvelope<DnsResponse, InetSocketAddress>>> i = queriesInProgress.iterator(); i.hasNext(); ) {
|
||||
Future<AddressedEnvelope<DnsResponse, InetSocketAddress>> f = i.next();
|
||||
for (Iterator<Future<DnsResponse>> i = queriesInProgress.iterator(); i.hasNext(); ) {
|
||||
Future<DnsResponse> f = i.next();
|
||||
i.remove();
|
||||
|
||||
if (!f.cancel(false)) {
|
||||
|
|
|
@ -24,7 +24,6 @@ import dorkbox.network.dns.DnsQuestion;
|
|||
import dorkbox.network.dns.DnsResponse;
|
||||
import dorkbox.network.dns.constants.DnsSection;
|
||||
import dorkbox.network.dns.records.DnsRecord;
|
||||
import io.netty.channel.AddressedEnvelope;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
|
@ -42,7 +41,7 @@ class DnsQueryContext {
|
|||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(DnsQueryContext.class);
|
||||
|
||||
private final DnsNameResolver parent;
|
||||
private final Promise<AddressedEnvelope<DnsResponse, InetSocketAddress>> promise;
|
||||
private final Promise<DnsResponse> promise;
|
||||
private final int id;
|
||||
private final DnsQuestion question;
|
||||
|
||||
|
@ -53,7 +52,7 @@ class DnsQueryContext {
|
|||
DnsQueryContext(DnsNameResolver parent,
|
||||
InetSocketAddress nameServerAddr,
|
||||
DnsQuestion question,
|
||||
Promise<AddressedEnvelope<DnsResponse, InetSocketAddress>> promise) {
|
||||
Promise<DnsResponse> promise) {
|
||||
|
||||
this.parent = checkNotNull(parent, "parent");
|
||||
this.nameServerAddr = checkNotNull(nameServerAddr, "nameServerAddr");
|
||||
|
@ -175,29 +174,28 @@ class DnsQueryContext {
|
|||
promise.tryFailure(e);
|
||||
}
|
||||
|
||||
void finish(AddressedEnvelope<DnsResponse, InetSocketAddress> envelope) {
|
||||
final DnsResponse response = envelope.content();
|
||||
void finish(DnsResponse response) {
|
||||
|
||||
try {
|
||||
DnsRecord[] sectionArray = response.getSectionArray(DnsSection.QUESTION);
|
||||
if (sectionArray.length != 1) {
|
||||
logger.warn("Received a DNS response with invalid number of questions: {}", envelope);
|
||||
logger.warn("Received a DNS response with invalid number of questions: {}", response);
|
||||
return;
|
||||
}
|
||||
|
||||
DnsRecord[] questionArray = question.getSectionArray(DnsSection.QUESTION);
|
||||
if (questionArray.length != 1) {
|
||||
logger.warn("Received a DNS response with invalid number of query questions: {}", envelope);
|
||||
logger.warn("Received a DNS response with invalid number of query questions: {}", response);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!questionArray[0].equals(sectionArray[0])) {
|
||||
logger.warn("Received a mismatching DNS response: {}", envelope);
|
||||
logger.warn("Received a mismatching DNS response: {}", response);
|
||||
return;
|
||||
}
|
||||
|
||||
setSuccess(envelope);
|
||||
setSuccess(response);
|
||||
} finally {
|
||||
if (question.isResolveQuestion()) {
|
||||
// for resolve questions (always A/AAAA), we convert the answer into InetAddress, however with OTHER TYPES, we pass
|
||||
|
@ -208,7 +206,7 @@ class DnsQueryContext {
|
|||
}
|
||||
|
||||
private
|
||||
void setSuccess(AddressedEnvelope<DnsResponse, InetSocketAddress> envelope) {
|
||||
void setSuccess(DnsResponse response) {
|
||||
parent.queryContextManager.remove(nameServerAddr(), id);
|
||||
|
||||
// Cancel the timeout task.
|
||||
|
@ -217,17 +215,16 @@ class DnsQueryContext {
|
|||
timeoutFuture.cancel(false);
|
||||
}
|
||||
|
||||
Promise<AddressedEnvelope<DnsResponse, InetSocketAddress>> promise = this.promise;
|
||||
Promise<DnsResponse> promise = this.promise;
|
||||
if (promise.setUncancellable()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
AddressedEnvelope<DnsResponse, InetSocketAddress> castResponse = envelope.retain();
|
||||
// envelope now has a refCnt = 2
|
||||
if (!promise.trySuccess(castResponse)) { // question is used here!
|
||||
response.retain();
|
||||
// response now has a refCnt = 2
|
||||
if (!promise.trySuccess(response)) { // question is used here!
|
||||
// We failed to notify the promise as it was failed before, thus we need to release the envelope
|
||||
envelope.release();
|
||||
response.release();
|
||||
}
|
||||
|
||||
envelope.release();
|
||||
response.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user