Added more DNS required files
This commit is contained in:
parent
762215304d
commit
873e3e9863
76
src/dorkbox/network/dns/DatagramDnsQueryEncoder.java
Normal file
76
src/dorkbox/network/dns/DatagramDnsQueryEncoder.java
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
import dorkbox.network.dns.records.DnsMessage;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.AddressedEnvelope;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
/**
|
||||
* Encodes an {@link AddressedEnvelope} of {@link DnsQuestion}} into a {@link DatagramPacket}.
|
||||
*/
|
||||
@UnstableApi
|
||||
@ChannelHandler.Sharable
|
||||
public
|
||||
class DatagramDnsQueryEncoder extends MessageToMessageEncoder<AddressedEnvelope<DnsQuestion, InetSocketAddress>> {
|
||||
|
||||
private final int maxPayloadSize;
|
||||
|
||||
/**
|
||||
* Creates a new encoder
|
||||
*/
|
||||
public
|
||||
DatagramDnsQueryEncoder(int maxPayloadSize) {
|
||||
this.maxPayloadSize = maxPayloadSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected
|
||||
void encode(ChannelHandlerContext ctx, AddressedEnvelope<DnsQuestion, InetSocketAddress> in, List<Object> out) throws Exception {
|
||||
|
||||
final InetSocketAddress recipient = in.recipient();
|
||||
final DnsMessage query = in.content();
|
||||
final ByteBuf buf = ctx.alloc()
|
||||
.ioBuffer(maxPayloadSize);
|
||||
|
||||
boolean success = false;
|
||||
try {
|
||||
DnsOutput dnsOutput = new DnsOutput(buf);
|
||||
query.toWire(dnsOutput);
|
||||
success = true;
|
||||
} finally {
|
||||
if (!success) {
|
||||
buf.release();
|
||||
}
|
||||
}
|
||||
|
||||
out.add(new DatagramPacket(buf, recipient, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
|
||||
cause.printStackTrace();
|
||||
}
|
||||
}
|
55
src/dorkbox/network/dns/DatagramDnsResponseDecoder.java
Normal file
55
src/dorkbox/network/dns/DatagramDnsResponseDecoder.java
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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.util.List;
|
||||
|
||||
import dorkbox.network.dns.exceptions.WireParseException;
|
||||
import dorkbox.network.dns.records.Header;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import io.netty.util.internal.UnstableApi;
|
||||
|
||||
/**
|
||||
* Decodes a {@link DatagramPacket} into a {@link DnsResponse}.
|
||||
*/
|
||||
@UnstableApi
|
||||
@ChannelHandler.Sharable
|
||||
public class DatagramDnsResponseDecoder extends MessageToMessageDecoder<DatagramPacket> {
|
||||
|
||||
/**
|
||||
* Creates a new DNS Response decoder
|
||||
*/
|
||||
public DatagramDnsResponseDecoder() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, DatagramPacket packet, List<Object> out) throws Exception {
|
||||
final ByteBuf buf = packet.content();
|
||||
|
||||
// Check that the response is long enough.
|
||||
if (buf.readableBytes() < Header.LENGTH) {
|
||||
throw new WireParseException("invalid DNS header - " + "too short");
|
||||
}
|
||||
|
||||
DnsInput dnsInput = new DnsInput(buf);
|
||||
DnsResponse dnsMessage = new DnsResponse(packet.sender(), packet.recipient(), dnsInput);
|
||||
out.add(dnsMessage);
|
||||
}
|
||||
}
|
228
src/dorkbox/network/dns/DnsQuestion.java
Normal file
228
src/dorkbox/network/dns/DnsQuestion.java
Normal file
|
@ -0,0 +1,228 @@
|
|||
package dorkbox.network.dns;
|
||||
|
||||
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||
|
||||
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.records.DnsRecord;
|
||||
import io.netty.channel.AddressedEnvelope;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static
|
||||
DnsQuestion newResolveQuestion(final String inetHost, final int type, final boolean isRecursionDesired) {
|
||||
return newQuestion(inetHost, type, isRecursionDesired, true);
|
||||
}
|
||||
|
||||
public static
|
||||
DnsQuestion newQuery(final String inetHost, final int type, final boolean isRecursionDesired) {
|
||||
return newQuestion(inetHost, type, isRecursionDesired, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static
|
||||
DnsQuestion newQuestion(final String inetHost, final int type, final boolean isRecursionDesired, boolean isResolveQuestion) {
|
||||
|
||||
// Convert to ASCII which will also check that the length is not too big.
|
||||
// See:
|
||||
// - https://github.com/netty/netty/issues/4937
|
||||
// - https://github.com/netty/netty/issues/4935
|
||||
String hostname = hostname(checkNotNull(inetHost, "hostname"));
|
||||
|
||||
if (hostname == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
hostname = hostname.toLowerCase(Locale.US);
|
||||
|
||||
if (type == DnsRecordType.A || type == DnsRecordType.AAAA) {
|
||||
// resolving a hostname -> ip address, the hostname MUST end in a dot
|
||||
hostname = appendTrailingDot(hostname);
|
||||
}
|
||||
|
||||
try {
|
||||
DnsRecord questionRecord = DnsRecord.newRecord(Name.fromString(hostname), type, DnsClass.IN);
|
||||
DnsQuestion question = new DnsQuestion(isResolveQuestion);
|
||||
question.getHeader()
|
||||
.setOpcode(DnsOpCode.QUERY);
|
||||
|
||||
if (isRecursionDesired) {
|
||||
question.getHeader()
|
||||
.setFlag(Flags.RD);
|
||||
}
|
||||
question.addRecord(questionRecord, DnsSection.QUESTION);
|
||||
|
||||
// keep the question around so we can compare the response to it.
|
||||
question.retain();
|
||||
|
||||
return question;
|
||||
} catch (Exception e) {
|
||||
// Name.fromString may throw a TextParseException if it fails to parse
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static
|
||||
String hostname(String inetHost) {
|
||||
try {
|
||||
String hostname = java.net.IDN.toASCII(inetHost);
|
||||
|
||||
// Check for http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6894622
|
||||
if (StringUtil.endsWith(inetHost, '.') && !StringUtil.endsWith(hostname, '.')) {
|
||||
return hostname + '.';
|
||||
}
|
||||
|
||||
return hostname;
|
||||
} catch (Exception e) {
|
||||
// java.net.IDN.toASCII(...) may throw an IllegalArgumentException if it fails to parse the hostname
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static
|
||||
String appendTrailingDot(String hostname) {
|
||||
if (!StringUtil.endsWith(hostname, '.')) {
|
||||
return hostname + '.';
|
||||
}
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public
|
||||
void init(int id, InetSocketAddress recipient) {
|
||||
getHeader().setID(id);
|
||||
this.recipient = 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(obj instanceof AddressedEnvelope)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final AddressedEnvelope<?, SocketAddress> that = (AddressedEnvelope<?, SocketAddress>) obj;
|
||||
if (sender() == null) {
|
||||
if (that.sender() != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!sender().equals(that.sender())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (recipient() == null) {
|
||||
if (that.recipient() != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
142
src/dorkbox/network/dns/DnsResponse.java
Normal file
142
src/dorkbox/network/dns/DnsResponse.java
Normal file
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you 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 java.net.SocketAddress;
|
||||
|
||||
import dorkbox.network.dns.records.DnsMessage;
|
||||
import io.netty.channel.AddressedEnvelope;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param sender the address of the sender
|
||||
* @param recipient the address of the recipient
|
||||
*/
|
||||
public
|
||||
DnsResponse(InetSocketAddress sender, InetSocketAddress recipient, final DnsInput dnsInput) throws IOException {
|
||||
super(dnsInput);
|
||||
|
||||
if (recipient == null && sender == null) {
|
||||
throw new NullPointerException("recipient and sender");
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@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) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(obj instanceof AddressedEnvelope)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final AddressedEnvelope<?, SocketAddress> that = (AddressedEnvelope<?, SocketAddress>) obj;
|
||||
if (sender() == null) {
|
||||
if (that.sender() != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!sender().equals(that.sender())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (recipient() == null) {
|
||||
if (that.recipient() != null) {
|
||||
return false;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user