Simplified resolver via DnsResponse->DnsEnvelope for all promise types

This commit is contained in:
nathan 2018-01-29 00:49:17 +01:00
parent dc54c9b226
commit 12c7c9f0a5
6 changed files with 231 additions and 262 deletions

View 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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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)) {

View File

@ -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();
}
}
}